2013-02-19 42 views
1

我想查找關於如何使用自定義對象作爲HashMap的關鍵字或存儲在HashSet中的對象的權威性文檔。將Java HashSet/HashMap自定義對象作爲關鍵字的權威性文檔?

從閱讀各種帖子,我發現你應該重寫自定義對象(例如Overriding equals and hashCode in Java)中的equals()和hashCode()兩個方法。

但是,當我閱讀Oracle/Sun官方Javadocs的HashSetHashMap時,他們根本沒有提到重寫這些方法。這些說明是否埋在文檔的其他地方?如果是這樣,我可以在哪裏找到它們?

回答

0

Collections API根據equals()和hashCode()來描述契約。如果你想讓一個鍵的多個實例相互相等,那麼你需要重寫equals()和hashCode(),遵循Object類指定的協議。

Set interface描述了它的合同:

更正式地,集包含沒有對元素e1和e2,使得 e1.equals(E2),和至多一個空元素。正如其名稱 所暗示的那樣,該接口對數學集抽象進行建模。

equals()和hashCode()的約定由Object類指定。

在「有效的Java」,約書亞布洛赫建議您始終覆蓋hashCode當你重寫equals,避免違反這些合同。

+0

(1)所以說明是間接達成的,對吧? HashSet導致Set,其中提到了Object()中定義的equals()。 (2)如果我使用TreeSet而不是HashSet,我只需要在自定義對象中重寫Comparable(或者爲TreeSet提供一個Comparator),對吧? TreeSet沒有提及equals()或hashCode()。 – stackoverflowuser2010 2013-02-20 00:24:02

+0

「對象」中定義了「equals」和「hashCode」的聯繫人,因爲那是定義這些方法的地方。你應該以一致的方式定義它們,而不管你是否要在'HashSet'中使用它們。讓每個容器爲這些方法定義自己的合同是沒有意義的,因爲任何對象都只能選擇一個實現 - 這意味着所有集合都應該就如何使用這些方法達成一致。 同樣,你對'overriding'的關注是錯位的。你永遠不必重寫任何這些方法 - 只要確保它們的一致性定義。 – BeeOnRope 2013-02-20 00:54:21

+0

@ stackoverflowuser2010他們不是間接的。正如我在答覆中所說的,它們在「Set」和「Map」的文檔中指出。這些是強加限制的界面,所以這就是人們想要看的地方。 HashMap,HashSet,TreeSet只是簡單的實現,而不是指定合約的目的,而是爲了兌現它們。 – entonio 2013-02-20 02:10:40

0

SetMap的文檔中,它們是它們實現的接口。

這個要求並不是任意的,它是確保接口的方法按預期工作的唯一方法 - 通過能夠分辨何時可能是不同的Java對象的鍵應該被視爲相同的鍵或不 - 例如,​​和"ab" + "c"是不同的對象,但equals的實現確保它們被認爲是相同的密鑰。至於hashCode,需要在這些接口的數據結構中找到有意義的位置。

0

據我所知,鑰匙必須是一個不可變對象。

如果它是可變的,它的哈希代碼可以在添加到地圖後更改。發現它

Setting own class as key in java Hashmap

這裏 然後,地圖可以有一個問題是,說明這一個例子:

import java.util.HashMap; 
class Test{ 

    public int i=0; 
    @Override 
    public int hashCode() { 
     return i; 
    } 
} 

public class Main { 
    public static void main(String[] args) { 

     HashMap<Test, String> hm = new HashMap<>(); 
     Test t1 = new Test(); 
     hm.put(t1, "found"); 

     System.out.println(hm.get(t1)); 

     t1.i=2; 

     System.out.println(hm.get(t1)); 


    } 


} 

/* 
output: 
found 
null 
*/ 
3

你不需要覆蓋equalshashCode,但你確實需要有一致的equalshashCode方法。

也就是說,如果obj.equals(obj2),那麼它一定是obj.hashCode() == obj2.hashCode()的情況。相反的(非equals()對象具有不等於hashCode()值)應該儘可能經常以獲得良好性能,但這不是一個要求,並且如果您的對象具有超過2^32個狀態,則不能始終滿足)。

默認equals()hashCode()方法服從這一點,並具有身份語義 - 對象只有在它們實際上是相同的對象(obj == obj2)時才相等。

如果您想要值語義 - 例如,兩個具有相同狀態的對象相等,您應該重寫這些方法。

+0

這不回答我的問題。在HashSet/HashTree中使用這兩種方法的權威性文檔在哪裏? Stackoverflow的答案,儘管我很欣賞他們,但不是權威性的文檔。 – stackoverflowuser2010 2013-02-20 00:25:23

+1

有一個[良好的答案](http://stackoverflow.com/a/14970001/149138)下面鏈接到Oracle javadoc的'對象',它更正式地記錄它們。 – BeeOnRope 2013-02-20 00:51:51

+0

請考慮使用不可變的數據類型! – cIph3r 2013-02-20 00:57:28