2016-01-06 90 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

相關問題