2012-09-14 47 views
5

嘿,我正在使用HashMap來跟蹤BulletinBoard上的服務和服務請求。但是,我必須擁有哈希碼並且等於錯誤,因爲我得到重複密鑰。任何人都可以告訴爲什麼這可能是?爲什麼我的HashMap允許重複鍵?

鍵集的內容:

Services: [1, 1, 6, 6, 3] 
Requests: [8, 7, 6, 5, 8, 4, 5, 6, 2] 

下面是相關代碼:

private static final HashMap<Advert, Integer> services = new HashMap<>(); 
... 

public class Advert { 

private int id; 
private BoardPoster poster; 

public Advert(BoardPoster poster) { 
    this.poster = poster; 
} 

public BoardPoster getPoster() { 
    return poster; 
} 

public void spawn() { 
    id = RANDOM.nextInt(ADVERT_RANGE); 
} 

public int getID() { 
    return id; 
} 

@Override 
public String toString() { 
    return Integer.toString(id); 
} 

@Override 
public boolean equals(Object o) { 
    if (o != null && o instanceof Advert) { 
     return ((Advert) o).id == id; 
    } 
    return false; 
} 

@Override 
public int hashCode() { 
    return 67 * 5 + this.id; 
} 
} 
+4

一句話:檢查'o!= null && instanceof Advert'是多餘的。如果'o'爲'null',則instanceof Advert'返回'false'。在Java中,'null'不被認爲是任何類型的東西,因此所有的實例檢查都失敗。 – Brian

+1

因爲'id'是一個'int',所以你可以簡化你的hashcode:'return this.id;'。 – assylias

+0

@assylias這是一種做哈希碼的不好的方法,因爲它實際上不是哈希碼。返回'this.id%1000'可能是更好的選擇。 –

回答

18

最有可能的原因是,你作爲按鍵使用對象是可變的。所以如果你做的是這樣的:

map.put(anAdvert, 1); 
anAdvert.spawn(); //modifies id, which affects hashcode and equals 

地圖的行爲將是意想不到的。

CF Map's javadoc

注意:如果使用可變對象作爲map的key很大,一定要小心。如果對象的值以影響等於比較的方式更改,而對象是地圖中的關鍵字,則不會指定地圖的行爲。

+6

+1爲可變密鑰。 – kosa

+0

對於像這樣的屬性,最好使用'final'關鍵字。 –

+1

切勿將可變對象用作地圖鍵! –