2012-12-01 60 views
1

我試圖檢索一個對象作爲Map中的一個鍵,當我更改它的一個實例變量時。就我而言,當我在Map結構中搜索關鍵對象時,它應該在hashCode方法返回與最初相同的值時出現。然而,基於下面的代碼,我不能檢索通過方法獲得對象()具有改變的可變重量的值:檢索地圖中的對象

public class Car implements Comparable<Car> { 

int weight; 
String name; 

public Car(int w, String n) { 
    weight=w; 
    name=n; 
} 

public boolean equals(Object o){ 
    if(o instanceof Car){ 
     Car d = (Car)o; 
     return ((d.name.equals(name)) && (d.weight==weight)); 
    } 
    return false; 

} 

public int hashCode(){ 
    return weight/2 + 17; 
} 

public String toString(){ 
    return "I am " +name+ " with weight: "+weight; 
} 


public int compareTo(Car d){ 
    if(this.weight>d.weight) 
     return 1; 
    else if(this.weight<d.weight) 
     return -1; 
    else 
     return this.name.compareTo(d.name); 
} 

} 


public static void main(String[] args) { 
    Car d1 = new Car(107, "a"); 
    Car d2 = new Car(110, "b"); 
    Car d3 = new Car(110, "c"); 
    Car d4 = new Car(107, "a"); 

    Map<Car, Integer> m = new HashMap<Car, Integer>(); 
    m.put(d1, 1); 
    m.put(d2, 2); 
    m.put(d3, 3); 
    m.put(d4, 16); 

    System.out.println(m.get(d1).toString()); 
    d1.weight = 34; 
    System.out.println(m.get(new Car(34, "a"))); 

    for(Map.Entry<Car, Integer> me : m.entrySet()) 
     System.out.println(me.getKey().toString() + " value: " +me.getValue()); 

} 

的輸出是:

16 

null 

I am a with weight: 34 16 

I am c with weight: 110 3 

I am b with weight: 110 2 

但是,如果我做不改變權重的值(省略行:d1.weight = 34;),只是使用的代碼行:

System.out.println(m.get(new Car(107, "a"))); 

輸出爲:

16 

16 

I am a with weight: 107 value: 16 

I am c with weight: 110 value: 3 

I am b with weight: 110 value: 2 

它發現實際上的對象。它是以兩種方式達到預期的輸出,還是應該在第一版中找到並檢索該對象?

回答

6

將可變對象存儲爲散列表中的鍵時,應該非常小心。哈希代碼僅在對象插入時計算一次。如果稍後以影響哈希代碼的方式更改對象,很可能無法找到它。

您需要刪除該對象,並在進行此類更改時重新插入該對象。

+1

特別是,OP認爲它只是'hashCode'必須保持不變纔是錯誤的:equals結果必須保持不變。 (但一般來說,你只能使用不可變對象作爲映射鍵。) –

0
System.out.println(m.get(new Car(34, "a"))); 

你的地圖在這裏返回null,因爲它不包含關鍵對象與哈希碼34

然而,隨着

System.out.println(m.get(new Car(107, "a"))); 

地圖並返回一個對象,因爲它包含了關鍵對象使用散列碼70.