2012-09-14 43 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

切勿将可变对象用作地图键! –