2014-12-20 70 views
1

我已經創建了一個名爲Coordinates的類,它只保留一些xy整數。我想用這個作爲HashMap的關鍵。創建可用作散列映射關鍵字的Java類

不過,我注意到,當你創建的Coordinates兩個不同的實例具有相同xy值,它們被用作通過散列圖不同的密鑰。也就是說,即使它們都具有相同的座標,也可以放入兩個條目。

我已經重寫equals()

public boolean equals(Object obj) { 
    if (!(obj instanceof Coord)) { 
     return false; 
    }else if (obj == this) { 
     return true; 
    } 
    Coord other = (Coord)obj; 
    return (x == other.x && y == other.y); 
} 

HashMap仍然採用了兩個實例,好像他們是不同的密鑰。我該怎麼辦?

而且我知道我可以用兩個元素的整數數組來代替。但我想用這個班。

+7

你重寫了'hashcode'嗎? –

+0

@鄒鄒哦,不,我不知道。我看到它返回一個整數。我應該返回什麼?當然,這不是x和y的總和。 – Voldemort

+1

你需要保持一致。如果a等於b,則a.hashcode == b.hashcode。另請參見http://stackoverflow.com/questions/27581/what-issues-should-be-considered-when-overriding-equals-and-hashcode-in-java –

回答

6

你需要重寫hashCode。 Java 7爲此提供了一種實用方法。

@Override 
public int hashCode() { 
    return Objects.hash(x, y); 
} 
+1

爲什麼它需要將是很好的說明,但指出了該實用程序類感謝,我不知道它,它提供了一些有用的方法:) – Dici

+0

從http://tutorials.jenkov.com/java-collections/hashcode-equals.html *當插入對象使用一個密鑰hastable。計算此密鑰的哈希碼,並用於確定內部存儲對象的位置。當你需要在散列表中查找一個對象時,你也可以使用一個鍵。計算該密鑰的哈希碼並用於確定在哪裏搜索該對象。* – wassgren

4

你也應該重寫hashCode(),這樣兩個相等的情況下,具有相同的hashCode()。例如: -

@Override 
public int hashCode() { 
    int result = x; 
    result = 31 * result + y; 
    return result; 
} 

注意,它不是嚴格要求的兩個實例中不等於有不同的散列碼,但你有少的碰撞,更好的性能,你會得到從你們HashMap

1

哈希映射使用對象的hashCode方法來確定將對象放入哪個存儲桶。 如果您的對象不執行hashCode,它將繼承Object的默認實現。從docs

儘管合理實用,類Object定義的hashCode方法確實爲不同的對象返回不同的整數。 (這通常通過將對象的內部地址轉換爲整數來實現,但JavaTM編程語言不需要此實現技術。)

因此,每個對象看起來都是不同的。

需要注意的是不同的對象可能會返回相同hashCode。這就是所謂的衝突。 當發生這種情況時, 然後除了hashCode, 哈希映射實現將使用equals方法來確定兩個對象是否相等。

請注意,大多數IDE提供從您的類中定義的字段生成equalshashCode方法。實際上,IntelliJ鼓勵同時定義這兩種方法。有充分的理由。這兩種方法有密切的關係, ,只要你改變了其中的一個,或實現其中之一,或重寫其中之一, 必須查看(並極有可能改變),另一隻也。

這個類中的方法是100%,生成的代碼(通過的IntelliJ):

class Coord { 
    private int x; 
    private int y; 

    @Override 
    public boolean equals(Object o) { 
     if (this == o) return true; 
     if (o == null || getClass() != o.getClass()) return false; 

     Coord coord = (Coord) o; 

     if (x != coord.x) return false; 
     if (y != coord.y) return false; 

     return true; 
    } 

    @Override 
    public int hashCode() { 
     int result = x; 
     result = 31 * result + y; 
     return result; 
    } 
} 
0

你可能沒有覆蓋hashCode方法。爲什麼要求?要回答這個問題,你必須瞭解哈希表的工作原理。

的散列表是基本上linkedlists的陣列。陣列中的每個桶對應於特定值hashCode % numberOfBuckets。都具有相同的hashCode % numberOfBuckets對象將被存儲在鏈表內的相關聯的桶和將認識基礎上他們的equals方法(查找例如期間)。因此,確切的規格是a.hashCode() != b.hashCode() => !a.equals(b),相當於a.equals(b) => a.hashCode() == b.hashCode()

如果您使用基於引用的默認實現hashCode,那麼兩個相等但具有不同引用(因此,最可能是不同的hashCode)的對象將存儲在不同的存儲桶中,導致重複的密鑰。