2011-05-31 126 views
16

有什麼方法可以覆蓋Set數據類型使用的equals方法嗎?我爲一個叫Fee的類寫了一個自定義的equals方法。現在我有的Fee,我想確保沒有重複的條目。因此,我正在考慮使用中的Set,但決定兩個費用是否相等的標準存在於Fee類中的覆蓋equals方法中。Java集合集合 - 覆蓋等於方法

如果使用LinkedList,我將不得不遍歷每一個列表項,並呼籲在Fee類重寫equals方法與其餘條目作爲參數。僅僅閱讀它聽起來太多了,並且會增加計算複雜度。

我可以使用Set和覆蓋的equals方法嗎?我是不是該?

回答

3

Set使用添加到集合中的對象的equals方法。 JavaDoc狀態

一個不包含重複元素的集合。更正式地,集合不包含e1和e2這樣的元素對,使得e1.equals(e2)和至多一個空元素。

Set.equals()方法僅用於比較兩組之間是否相等。它從未用作添加/刪除集合中的項目的一部分。

-1

有PredicatedList或PredicatedSet在Apache Commons Collection

+1

你能詳細說明這是如何回答OP嗎?我正在尋找一種方法來忽略大寫/小寫'Set .contains(「foo」)' – 2014-07-16 08:49:28

30

傑夫福斯特說:

的Set.equals()方法僅用於比較兩個組的相等性。

可以使用Set擺脫重複條目,但要注意:HashSet不使用其包含的對象equals()方法來確定的平等。

HashSet一個攜帶有內部HashMap<Integer(HashCode), Object>條目,並使用equals()方法以及在的HashCode的equals方法來確定平等。要解決這個問題

的一種方法是重寫hashCode()在你把設置類,所以它代表你equals()標準

例如:

class Fee { 
     String name; 

    public boolean equals(Object o) { 
     return (o instanceof Fee) && ((Fee)o.getName()).equals(this.getName()); 
    } 

    public int hashCode() { 
     return name.hashCode(); 
    } 

} 
+4

'HashSet'遵循'Set'合同,它需要使用equals()方法來確定相等性。但是它利用了這樣一個事實:如果Object的equals()是另一個對象,那麼它需要具有相同的'hashCode()'。你可以**在單個'HashSet'中有多個具有相同'hashCode()'值的對象。 – Martin 2013-11-14 21:25:15

+0

好點馬丁。我只是在一個小測試應用程序中進行了驗證。如果添加一個既不等於NOR的對象又具有與set-objects相同的hashCode,則它將作爲新對象添加。我在我的回答中澄清了這一點。 – 2013-12-02 12:55:25

6

可以和應該使用一個Set用來保存一個覆蓋了equals方法的對象類型,,但你也可能需要重寫hashCode()。等號對象必須具有相同的散列碼。

例如:

public Fee{ 

    public String fi; 

    public String fo; 

    public int hashCode(){ 

     return fi.hashCode()^fo.hashCode(); 
    } 

    public boolean equals(Object obj){ 

     return fi.equals(obj.fi) && fo.equals(obj.fo); 
    } 
} 

(根據需要與null檢查,當然。)

集經常使用的hashCode(),以優化性能,並會表現不好,如果你的hashCode方法被破壞。例如,HashSet uses an internal HashMap.

If you check the source code of HashMap,你會看到它取決於兩個的hashCode()和equals()方法的元素的方法來確定的平等:

if (e.hash == hash && ((k = e.key) == key || key.equals(k))) { 

如果沒有正確生成散列,你的equals方法可能永遠不會被調用。

爲了讓您的設置更快,您應該儘可能爲不相等的對象生成不同的哈希碼。

+2

我知道這是一個例子,但不應該使用連接來生成hashCode。就像你說的那樣,hashCode方法可能會經常被調用,並且字符串連接是一個緩慢而昂貴的操作。 更好的方法是簡單地異或字符串hashCode。例如:'return fi.hashCode()^ fo.hashCode();' 此外,你的'equals()'方法有點過分殺死。 你不需要將'fi'與'fo'進行比較,然後將'fo'與'fi'進行比較。 Object' Javadoc明確說明'equals()'方法必須是對稱的。因此,只有performin'fi.equals(fo)'就足夠了(忽略'null')。 – Moinonime 2013-07-16 20:01:21

+0

感謝Mathieu。我編輯了我對XOR散列碼的回答,而不是連接字符串。我不認爲你對等號方法的評論是有效的。 fi.equals(fo)將完全不同,並且與我定義的hashCode方法不一致。 – SharkAlley 2013-07-20 07:17:09

1

一個解決方案是使用帶比較器的TreeSet

從文檔:被認爲等於通過該方法

TreeSet實例使用其的compareTo執行所有元件比較(或比較)的方法,因此兩個元件,從所述一組,相等的觀點出發。

這種方法比使用LinkedList快得多,但比HashSet(ln(n)vs n)慢一點。

值得注意的是使用TreeSet的一個副作用是你的集合被排序。