当插入重复键时,我对 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);
}
}
我期望的输出: 替换的记录名称:Terry,年龄:60 姓名:测试,年龄:60 姓名:特里,年龄:26 姓名:约翰,年龄:21
我得到的输出: 替换的记录名称:Terry,年龄:60 姓名:测试,年龄:60 姓名:特里,年龄:60 姓名:约翰,年龄:21
我期待 (Terry, 60) 被 (Terry, 26) 对象取代。当我得到替换的记录名称:Terry,年龄:60作为输出时,这似乎正在发生。但是, map 包含记录姓名:Terry,年龄:60,而不是姓名:Terry,年龄:26。
编辑:谢谢大家的建议。事实证明我犯了一个非常粗心的错误。我没有打印与键关联的值,而是仅打印键。
正如大家所指出的,解决方案是:
for(Emp e: emp.keySet())
{
Emp empVal = emp.get(e);
System.out.println("Name: " + empVal.name + " , age: " + empVal.age);
}
最佳答案
您的输出是打印键,而不是值。在您的代码中,键不会改变,但值会改变。
例如,如果您将输出循环更改为:
for (Emp emp : emp.values()) {
System.out.println("Name: " + e.name + " , age: " + e.age);
}
我怀疑您会看到您所期待的答案。
但是:总的来说,我建议不要这样做。各种代码都期望 if a.equals(b)
然后a
和b
根本没有任何有意义的差异,并且您的 Emp
类(class)equals
执行不符合该契约(Contract)。例如,如果您使用 HashSet
而不是HashMap
你会遇到更奇怪的行为,而且没有办法解决它。
实现这一点的更好方法可能是 Emp
的hashCode
和equals
方法正确地尊重姓名和年龄,并使您的 map 成为 Map<String, Emp>
其中键是员工姓名,值为 Emp
记录一下。
关于Java HashMap 插入重复键时,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12662917/