2012-09-30 193 views
2

當插入重複鍵時,我對Java HashMap有一個很基本的疑問。插入重複鍵時的Java HashMap

我的意圖是創建4個Emp對象。 2個對象(e1和e2)具有相同的hashCode。所以當插入e1(在e2之後插入)時,hashmap會意識到具有相同散列值的對象已經存在(對象e2)。然後它將比較槽中所有對象的密鑰與相同的散列值。如果它找到一個具有匹配鍵的對象(通過調用下面的Emp類的equals方法),它將用新值替換舊值。

請看看下面的測試代碼:

import java.util.Map; 
import java.util.HashMap; 
import java.util.Set; 

class Emp { 
     String name; 
     int age; 

     public Emp(String name, int age) { 
       this.name = name; 
       this.age = age; 
     } 

     public boolean equals(Object s) { 
       if(s instanceof Emp) { 
         Emp s1 = (Emp) s; 
         return ((s1.name.compareToIgnoreCase(this.name) == 0)); 
       } 
       return false; 
     } 

     public int hashCode() { 
       //return (this.name.hashCode() + this.age); 
       return this.name.hashCode(); 
     } 
} 

public class HashTest { 
     public static void main(String[] args) { 
       Emp e1 = new Emp("Terry", 26); 
       Emp e2 = new Emp("Terry" , 60); 
       Emp e3 = new Emp("John", 21); 
       Emp e4 = new Emp("Test", 60); 

       Map<Emp,Emp> emp = new HashMap<Emp, Emp>(); 
       emp.put(e2,e2); 
       Emp v2 = emp.put(e1,e1); 
       emp.put(e3,e3); 
       emp.put(e4,e4); 

       System.out.println("Replaced Record Name: " + v2.name + " , age: " + v2.age); 
       for(Emp e: emp.keySet()) 
         System.out.println("Name: " + e.name + " , age: " + e.age); 
     } 
} 

輸出我所期待的: 替換記錄名字:特里,年齡:60 名稱:測試,年齡:60 名稱:特里,年齡:26 名稱:約翰,年齡:21

我得到的輸出: 替換記錄名字:特里,年齡: 60 名稱:測試,年齡:60 名稱:特里,年齡:60 名稱:約翰,年齡:21

我期待(特里,60)由(特里,26)對象替換。這似乎正在發生,因爲我得到替換記錄名稱:特里,年齡:60作爲輸出。但是,地圖中包含記錄姓名:Terry,年齡:60而不是姓名:Terry,年齡:26

編輯:謝謝大家的建議。事實證明,我犯了一個非常粗心的錯誤。不是打印與關鍵字相關的值,而是僅打印關鍵字。

正如每個人所指出的,解決的辦法是:

for(Emp e: emp.keySet()) 
    { 
     Emp empVal = emp.get(e); 
     System.out.println("Name: " + empVal.name + " , age: " + empVal.age); 
    } 

回答

2

您的輸出打印鍵,而不是值。在你的代碼中,密鑰不會改變,但值會。

舉例來說,如果你改變你的輸出循環中:

for (Emp emp : emp.values()) { 
    System.out.println("Name: " + e.name + " , age: " + e.age); 
} 

我懷疑你會看到您所期望的答案。

但是:一般來說,我會建議不要做你在這裏做的事情。各種代碼預計如果a.equals(b)然後ab根本沒有任何有意義的差異,並且您的Emp類的equals實現不符合該合同。例如,如果您使用的是HashSet而不是HashMap,則會產生更多特殊行爲,因此無法解決該問題。

來實現,這可能是有EmphashCodeequals方法適當尊重名字和年齡,並讓您的地圖是Map<String, Emp>,其中的關鍵是員工的名字和值是Emp記錄更好的辦法。

+0

jacobm非常感謝您的支持。我在這個問題上頭痛了這麼久..討厭粗心的錯誤:( – FunBoy

0

我稍微修改了你的代碼 - 見下文。新的值放在地圖中,但由於鍵是平等的,所以第二個鍵重用了現有的鍵。

public static void main(String[] args) { 
    Emp e1 = new Emp("Terry", 26); 
    Emp e2 = new Emp("Terry", 60); 

    Map<Emp, Emp> emp = new HashMap<Emp, Emp>(); 
    emp.put(e2, e2); 
    Emp v2 = emp.put(e1, e1); 

    System.out.println("Replaced Record Name: " + v2.name + " , age: " + v2.age); 
    for (Emp e : emp.keySet()) { 
     System.out.println("[key] Name: " + e.name + " , age: " + e.age); 
     System.out.println("[value] Name: " + emp.get(e).name + " , age: " + emp.get(e).age); 
    } 
} 

輸出:

[key] Name: Terry , age: 60 
[value] Name: Terry , age: 26 
0

在下面的語句中,你實際上是打印鍵..通過調用keySet(),你在map鍵的Set,你遍歷這些鍵進行打印..你需要獲取從地圖這些鍵的值,並打印出來。所以,更改如下語句: -

System.out.println("Name: " + e.name + " , age: " + e.age); 

有: -

System.out.println("Name: " + emp.get(e).name + " , age: " + emp.get(e).age);