我今天早上遇到这种现象,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 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()...
顺便说一下,即使hashCode()没有被覆盖,同样的集合比较也在groovy中工作。
答案 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
完全相同。