为什么Java HashSet.equals()不检查对象是否相等?

xin*_*ing -1 java list equals set hashset

我今天早上来到这个现象,equals方法中Set没有检查元素的值是否相等List.这不符合java doc.

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)
Run Code Online (Sandbox Code Playgroud)

我做了一些研究.根据这个 Java doc for Set,HashSet equals,HashSet containsAll,HashSet包含,它将使用(o == null?e == null:o.equals(e))来检查元素是否相等.那么为什么会这样呢?任何人都可以给我一些暗示吗?

谢谢!

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

在Java中覆盖equals和hashCode时应该考虑哪些问题?

我重写了equals()但不是hashCode()......

顺便说一句,相同的集合比较在groovy中工作,即使hashCode()没有被覆盖.

Lou*_*man 8

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

对于另一种情况,HashSet利用其中的合同.equals规定,如果两个对象==彼此相对,则它们必须.equals彼此相对.HashSet这里的部分实现检查元素是否是==,如果是,它会跳过调用.equals.

如果每个方法都正确地实现了它的契约,那么这不能改变语义; HashSet将始终表现得像.equals被调用一样.

  • 查看`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`之前测试对象是否为`==`. (3认同)
  • @xing,然后你的对象违反了他们自己的`hashCode()`的契约.如果哈希码无效,则"HashSet"无效.任何两个`.equals`对象必须具有相同的`hashCode()`. (3认同)