为什么 Java HashSet.equals() 不检查对象是否相等?
Why does not Java HashSet.equals() check for object equality?
我今天早上遇到了这个现象,Set
中的 equals
方法不检查元素的值是否相等,而 List
会。这不符合 java 文档。
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 Set, HashSet equals , HashSet containsAll, HashSet contains,它将使用 (o==null ? e==null : o.equals(e)) 检查元素是否相等。那么为什么会这样呢?谁能给我一些提示?
谢谢!
------------这个问题的答案可以在这里找到------------
What issues should be considered when overriding equals and hashCode in Java?
我覆盖了 equals() 但没有覆盖 hashCode()...
顺便说一句,相同的集合比较在 groovy 中有效,即使没有覆盖 hashCode()。
HashSet
包括许多可以解释所有这一切的优化:首先,如果两个对象按其哈希码放入不同的桶中,或者如果它们具有完全不同的哈希码,则它们可能会跳过equals
电话。这是Object.hashCode
的合约允许的;如果两个对象具有不同的哈希码,则不允许它们相互 .equals
。
对于另一种情况,HashSet
利用了 .equals
的约定,该约定指定如果两个对象彼此 ==
,则它们必须 .equals
对彼此。 HashSet
的部分实现在这里检查元素是否为 ==
,如果是,它会跳过调用 .equals
.
如果每个方法都正确地实现了它的契约,这就不会改变语义; HashSet
将始终表现得就像 .equals
被调用一样。
我今天早上遇到了这个现象,Set
中的 equals
方法不检查元素的值是否相等,而 List
会。这不符合 java 文档。
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 Set, HashSet equals , HashSet containsAll, HashSet contains,它将使用 (o==null ? e==null : o.equals(e)) 检查元素是否相等。那么为什么会这样呢?谁能给我一些提示?
谢谢!
------------这个问题的答案可以在这里找到------------
What issues should be considered when overriding equals and hashCode in Java?
我覆盖了 equals() 但没有覆盖 hashCode()...
顺便说一句,相同的集合比较在 groovy 中有效,即使没有覆盖 hashCode()。
HashSet
包括许多可以解释所有这一切的优化:首先,如果两个对象按其哈希码放入不同的桶中,或者如果它们具有完全不同的哈希码,则它们可能会跳过equals
电话。这是Object.hashCode
的合约允许的;如果两个对象具有不同的哈希码,则不允许它们相互 .equals
。
对于另一种情况,HashSet
利用了 .equals
的约定,该约定指定如果两个对象彼此 ==
,则它们必须 .equals
对彼此。 HashSet
的部分实现在这里检查元素是否为 ==
,如果是,它会跳过调用 .equals
.
如果每个方法都正确地实现了它的契约,这就不会改变语义; HashSet
将始终表现得就像 .equals
被调用一样。