Java Crazyness - 当equals通过时包含失败 [英] Java Crazyness - Contains fails when equals passes

查看:169
本文介绍了Java Crazyness - 当equals通过时包含失败的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我在java(1.6)中看到的最疯狂的事情:

This is the most crazy thing I have seen in java (1.6):

Set<ActionPlan> actionPlans = assessment.getActionPlans();
//getActionPlans() returns a java.util.HashSet<ActionPlan>
ActionPlan actionPlan = actionPlans.iterator().next();
assertTrue(actionPlan1.equals(actionPlan));
assertEquals(actionPlan1.hashCode(), actionPlan.hashCode());
assertTrue(actionPlans.contains(actionPlan1));

前两个断言通过,但最后一个失败。

我没有向您提供ActionPlan和评估类的详细信息,因为它无关紧要。包含方法失败,其中equals和hash不会。

I'm not giving you details on the ActionPlan and Assessment classes because it shouldn't matter. The contains method fails where the equals and hash don't.

我不是说java已经破坏或其他任何东西,我的代码中可能会发生一些有趣的事情。

I'm not saying that java is broken or anything, there is probably something funny going on in my code.

请注意,我是一名经验丰富的java程序员,我知道dos并不知道实现equals和hashCode。因此,如果我的代码中缺少某些东西,那就不是显而易见的了。

Note that I'm an experienced java programmer and I'm aware of the dos and don't for implementing equals and hashCode. So if something is missing in my code it's not something obvious.

有没有人见过令人费解的东西?

Has anyone ever seen something that puzzling?

编辑

我在我的代码中做了一些研究,现在我认为问题出在休眠状态。我在创建之后,在代码的不同部分记录了ActionPlan对象的hashCode,直到调用失败的断言。 它没有改变

I did some research in my code and I now think the problem is in hibernate. I have logged the hashCode of the ActionPlan object, after creation, and at different parts of the code until the failing assert is getting called. It does not change.

我还检查了assessment.getActionPlans()返回的类,它是:

Also I have checked the class returned by assessment.getActionPlans() and it is:

org.hibernate.collection.internal.PersistentSet

我很想相信Set的这个实现不能正确使用equals或hashcode。

I'm tempted to believe that this implementation of Set does not use equals or hashcode properly.

有没有人对此有所了解?

Does anyone have insight on that?

推荐答案

有可能解释


  • 你有一个不使用equals或hashCode的有序集。

  • 你有覆盖等于(MyClass)而不是equals(对象)

  • hashCode使用的字段已更改。这使Set处于无法使用的状态。

测试最后一种可能性的最简单方法是尝试

The simplest way to test the last possibility is to try

assertTrue(new HashSet(actionPlans).contains(actionPlan1));

我怀疑这会在你的情况下通过。 ;)

I suspect this will pass in your case. ;)

日期有一个缺陷,它是可变的,hashCode使用那个可变字段,所以你可以破坏任何哈希集合它是通过改变它。当您更改compareTo中使用的字段时会发生类似的问题。

Date has a flaw that it is mutable and hashCode uses that mutable fields so you can corrupt any hash collection it is in by mutating it. A similar problem occurs when you alter a field which is used in compareTo.

Set<Date> dates = new HashSet<Date>();
SortedSet<Date> dates2 = new TreeSet<Date>();
Date d1 = new Date(1), d2 = new Date(2), d3 = new Date(3);
dates.add(d1);
dates.add(d2);
dates.add(d3);
dates2.add(d1);
dates2.add(d2);
dates2.add(d3);
d1.setTime(6);
d2.setTime(5);
d3.setTime(4);
System.out.print("The dates contains [");
for (Date date : dates) {
    System.out.print("date " + date.getTime() + " ");
}
System.out.println("]");
System.out.print("The sorted dates2 contains [");
for (Date date : dates2) {
    System.out.print("date " + date.getTime() + " ");
}
System.out.println("]");
for (int i = 1; i <= 6; i++)
    System.out.println("date " + i + " found is " + dates.contains(new Date(i))
            + " and " + dates2.contains(new Date(i)));

打印

The dates contains [date 6 date 5 date 4 ]
The sorted dates2 contains [date 6 date 5 date 4 ]
date 1 found is false and false
date 2 found is false and false
date 3 found is false and false
date 4 found is false and false
date 5 found is false and true
date 6 found is false and false

注意:已排序的集合现在的顺序错误。

Note: the sorted collection is now in the wrong order.

这篇关于Java Crazyness - 当equals通过时包含失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆