插入重复键时的Java HashMap

插入重复键时的Java HashMap,java,hashmap,Java,Hashmap,当插入重复键时,我对Java HashMap有一个非常基本的疑问 我的意图是创建4个Emp对象。2个对象(e1和e2)具有相同的哈希代码。因此,当插入e1(在e2之后插入)时,hashmap将意识到已经存在具有相同哈希值的对象(对象e2)。然后,它将比较插槽中具有相同哈希值的所有对象的键。如果它找到一个具有匹配键的对象(通过调用下面Emp类的equals方法),它将用新值替换旧值 请查看下面的测试代码: import java.util.Map; import java.util.HashMap

当插入重复键时,我对Java HashMap有一个非常基本的疑问

我的意图是创建4个Emp对象。2个对象(e1和e2)具有相同的哈希代码。因此,当插入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);
        }
}

您的输出是打印键,而不是值。在代码中,键不会更改,但值会更改

例如,如果将输出循环更改为:

for (Emp emp : emp.values()) {
  System.out.println("Name: " + e.name + " , age: " + e.age);
}
我想你会看到你期待的答案

然而:总的来说,我建议不要做你在这里做的事情。所有类型的代码都希望,如果
a.equals(b)
那么
a
b
没有任何有意义的区别,并且您的
Emp
类的
equals
实现不符合该契约。例如,如果您使用的是
HashSet
而不是
HashMap
,那么您将获得更为奇特的行为,并且无法修复它


实现这一点的更好方法可能是使用
Emp
hashCode
equals
方法适当地尊重姓名和年龄,并使您的地图成为
map
,其中键是员工的姓名,值是
Emp
记录。

我稍微修改了您的代码-见下文。新值放入映射中,但由于键相等,第二次放入将重用现有键

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);
    }
}

在下面的语句中,您实际上是在打印密钥。。通过调用
keySet()
,您可以在
map
中获得一组
键,然后迭代这些键并打印它们。。您需要从映射中获取这些键的值并打印它们。。因此,请更改以下声明:-

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

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

雅各布:谢谢你的好消息。这么长时间以来,我一直在为这个伤脑筋。。讨厌粗心的错误:(
System.out.println("Name: " + e.name + " , age: " + e.age);
System.out.println("Name: " + emp.get(e).name + " , age: " + emp.get(e).age);