2016-01-06 52 views
-3

今天早上我已经到了这种现象,Set中的equals方法不检查元素的值是否相等,而List。这不符合java文档。Java HashSet.equals()为什么不检查对象是否相等?

Set<MyClass> s1 = new HashSet<>(); 
Set<MyClass> s2 = new HashSet<>(); 
Set<MyClass> s3 = new HashSet<>(); 
Set<MyClass> s4 = new HashSet<>(); 
List<MyClass> l1 = new ArrayList<>(); 
List<MyClass> l2 = new ArrayList<>(); 

MyClass o1 = new MyClass(); 
MyClass o2 = new MyClass(); 

// **this gives false, and does not call MyClass.equals().** 
s1.add(o1); 
s2.add(o2); 
boolean setCompareWithDifferentObjects = s1.equals(s2); 

// this gives true, and also does not call MyClass.equals(). 
s3.add(o1); 
s4.add(o1); 
boolean setCompareWithSaveObjects = s3.equals(s4); 

// this give true, and MyClass.equals() is called. 
l1.add(o1); 
l2.add(o2); 
boolean listCompare = l1.equals(l2) 

我已经做了一些研究。根据这个 Java doc for SetHashSet equalsHashSet containsAllHashSet contains,它将使用(o == null?e == null:o.equals(e))来检查元素是否相等。那么为什么会这样呢?任何人都可以给我一些提示吗?

谢谢!

----------这个问题的答案可以在这里找到-----------

What issues should be considered when overriding equals and hashCode in Java?

我overrided equals()方法,但不是的hashCode ()...

btw,即使hashCode()没有被覆盖,也可以在groovy中工作。

+3

你是否已经正确实现了equals和hashcode方法? –

+0

我已经实现了MyClass.equals()而不是hashCode()。但在第一次比较中,即使==失败,MyClass.equals也不会被输入。 – xing

+5

感叹......如果你还没有实现'hashCode()',这就解释了你所看到的一切。 equals()和hashCode()必须相互一致。另外,请不要将代码重新输入到SO输入文本框中。总是复制/粘贴,以免引入转录错误('l2.add(l2)')。一个这样明显的错误会使您的整个代码示例受到怀疑,并导致不必要的澄清请求。 –

回答

6

HashSet包括许多优化,可以解释所有这些:首先,如果两个对象通过哈希代码放入不同的桶中,或者它们根本不同,则可以跳过equals调用。这是合同Object.hashCode允许的;如果两个对象有不同的哈希码,那么他们不允许彼此相互.equals

对于其他情况下,需要HashSet.equals合同中规定,如果两个对象==彼此,那么他们必须.equals彼此的优点。部分HashSet的实现在此检查元素是否为==,如果是,则跳过呼叫.equals

如果每个方法正确地执行它的约定,这不能改变语义; HashSet将始终表现得如同调用.equals一样。

+0

这在python中是一样的。我正在寻找证据。你可以链接任何? –

+3

看看'HashSet'的源代码,或者实际上''HashMap'。 [这里](http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/util/HashMap.java#HashMap.containsKey%28java.lang.Object% 29)是'HashMap.containsKey'的来源,如上所述,它只查看同一个桶,验证哈希是否完全相等,然后在调用equals之前测试对象是否为== ==。 –

+0

真正的问题是第一次检查,即使两个对象通过equals()方法相等,这也会导致错误。这意味着==给出false并且HashSet不会调用equals。这是我认为不符合合同的原因。 – xing

相关问题