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

时间:2016-01-06 00:04:35

标签: java list set equals 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)

我做过一些研究。根据这个 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?

我覆盖了equals()但没有覆盖hashCode()...

顺便说一下,即使hashCode()没有被覆盖,同样的集合比较也在groovy中工作。

1 个答案:

答案 0 :(得分:8)

HashSet包含许多可以解释所有这些的优化:首先,如果两个对象被哈希代码放入不同的桶中,或者它们根本就有不同的哈希码,它们可能会跳过{ {1}}致电。 equals的合同允许这样做;如果两个对象具有不同的哈希码,则不允许它们彼此Object.hashCode

对于另一种情况,.equals利用HashSet的合同,该合同规定如果两个对象彼此.equals,则它们必须==.equals彼此。 HashSet在此处实现的部分内容会检查元素是否为==,如果元素为.equals,则会跳过调用HashSet

如果每个方法都正确地实现了它的契约,那么这不能改变语义; .equals将始终表现得与调用Option Explicit On Imports System Imports System.Data Imports System.Data.Sql Imports System.Data.SqlClient Imports System.Diagnostics Imports Microsoft.VisualBasic Partial Class Reports01 Inherits System.Web.UI.Page Private Enum eFORMSTATE As Integer ... working VB code with methods and events follows... End Class 完全相同。