約定

2013-11-26 33 views
5

爲什麼,對於add()方法TreeSetHashSet狀態在Oracle Java API文檔:約定

如果在所述一組沒有E2元素e只添加其中(e==null ? e2==null : e.equals(e2))

然而,TreeSet使用compareTo(),而HashSet使用hashCode()確定平等。兩者都忽略equals()的值。我擔心文檔不準確,或者是我對約定或算法有錯誤的理解?

回答

2

你是正確的TreeSet文檔不正確。

對於HashSet你是錯誤的,因爲它確實使用equals()hashCode()而不是用於平等測試,僅用於快速搜索。

+0

如果hashCode()設置爲始終返回相同的代碼,那麼add()的行爲似乎取決於equals()。但是如果我創建了一個對象,其中equals()總是返回'true'並且不重寫hashCode() - 因此它對於不同的對象是不同的 - 然後add()會添加多個對象。所以add()的行爲似乎比文檔中陳述的更復雜。正如路易斯所說,這些情況不在合同範圍之內,但我對實施感興趣(因爲它沒有按照它的意思去做) - 任何人都知道是否有規範的規範? – user3038094

+0

@ user3038094 - 我會推薦閱讀HashMap的工作原理。那麼你就會明白爲什麼不總是調用'equals()'方法。不管從一般意義上講,HashSet _does_都使用equals()來進行相等性測試。 – jtahlborn

+0

謝謝jtahlborn - 我遵循你的建議,看看你的意思。如果hashCode()不同,那麼該算法不會麻煩評估equals(),如果hashCode()是相同的,則它只使用equals()。據推測這是因爲hashCode()被認爲比equals()更快,或者它是否需要評估hashCode()? 因此,最好在文檔中說: e == null? e2 == null:e.hashCode()== e2.hashCode()? e.hashCode()== e2.hashCode():e.equals(e2)== 0 – user3038094

1

TreeSet解釋了這個在其DOC:

注意,由一組(無論是否提供了明確的比較器)保持的順序必須與equals一致,如果要正確實現Set接口。 (請參閱Comparable或Comparator以獲得與equals一致的精確定義。)這是因爲Set接口是根據equals操作定義的,但TreeSet實例使用其compareTo(或compare)方法執行所有元素比較,所以兩個從這個方法看,被這個方法認爲是相等的元素是相等的。即使排序與等號不一致,集合的行爲也是明確定義的;它只是不服從Set接口的總體合同。

對於HashSet,這是對文檔隱含的期望,Set中的對象已正確實現;如果hashCode()未正確實施,則違反規範但不是HashSet,而是傳遞給它的對象。

+0

「即使集合的排序與等號不一致,集合的行爲也是明確定義的。」然而,行爲不像文檔中定義的那樣,這正是我想知道的。爲什麼文檔不具體(準確)呢?最好是說:e == null? e2 == null:e.compareTo(e2)== 0) – user3038094