2012-09-30 159 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);