简体   繁体   English

相同的对象用作Map中两个条目的键

[英]Same Object is used as key for two entries in Map

I have an Employee class as below. 我有一个如下的Employee类。

class Employee {
int empId;
String empName;

public Employee() {
}

Employee(int empId, String empName) {
    this.empId = empId;
    this.empName = empName;
}

public int getEmpId() {
    return empId;
}

public void setEmpId(int empId) {
    this.empId = empId;
}

public String getEmpName() {
    return empName;
}

public void setEmpName(String empName) {
    this.empName = empName;
}

@Override
public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + empId;
    result = prime * result + ((empName == null) ? 0 : empName.hashCode());
    return result;
}

@Override
public boolean equals(Object obj) {
    if (this == obj)
        return true;
    if (obj == null)
        return false;
    if (getClass() != obj.getClass())
        return false;
    Employee other = (Employee) obj;
    if (empId != other.empId)
        return false;
    if (empName == null) {
        if (other.empName != null)
            return false;
    } else if (!empName.equals(other.empName))
        return false;
    return true;
}}

I am using this Employee class object as key in my HashMap as below. 我在下面的HashMap中将此Employee类对象用作键。

    Map<Employee, String> empMap = new HashMap<>();
    Employee e1 = new Employee(123, "xyz");
    empMap.put(e1, "asd");
    System.out.println(empMap.size());
    System.out.println(empMap.get(e1));
    e1.setEmpId(122);
    empMap.put(e1, "asd");
    System.out.println(empMap.size());
    System.out.println(empMap.get(new Employee(122, "xyz")));
    System.out.println(empMap.get(new Employee(123, "xyz")));

    Set<Employee> mapEmpKeys = empMap.keySet();
    mapEmpKeys.forEach(emp -> {
        System.out.println("Employee ID: " + emp.getEmpId() + " Employee Name: " + emp.getEmpName());
    });

Output of the program: 1 asd 2 asd null Employee ID: 122 Employee Name: xyz Employee ID: 122 Employee Name: xyz 程序的输出: 1 asd 2 asd null Employee ID: 122 Employee Name: xyz Employee ID: 122 Employee Name: xyz

My question is even if the objects as keys are same, I am getting size of map as 2. Can someone please explain me that after changing Employee object e1 by setting its id to different value, and adding it again in map, gives size as 2 and when I am iterating over Key set of the map, I am getting same object for both the entries. 我的问题是,即使作为键的对象相同,我也得到了map的大小为2。有人可以向我解释一下,在将Employee对象e1设置为不同的值并将其再次添加到map中后,将Employee对象e1更改后,给出的大小为2,当我遍历地图的键集时,两个条目都得到相同的对象。 Keys must be unique in map, right? 键在地图中必须唯一,对吗? Then why I am getting same object key twice? 那为什么我两次获得相同的对象密钥? Thanks! 谢谢!

When you mutate an instance used as a key in a HashMap , if you modify properties used to determine equality or to calculate the hashCode() , you break the HashMap . 在对用作HashMap的键的实例进行突变时,如果修改用于确定相等性或计算hashCode()属性,则会破坏HashMap

The first time you put the key in the Map, it was put in the bucket that corresponds with the hashCode() computed based on the values 123 and "xyz". 第一次将密钥放入Map时,将其放入与基于值123和“ xyz”计算的hashCode()相对应的存储桶中。

The second time you put the same key in the Map, it was put in a different bucket that corresponds with the hashCode() computed based on the values 122 and "xyz". 第二次将相同的密钥放入Map中时,将其放入与基于值122和“ xyz”计算出的hashCode()相对应的其他存储桶中。

Since HashMap first locates the bucket matching a key's hashCode() , and only later checks all the keys in that bucket for key equality, if the hashCode() of a given key has changed, the second call to put will try to find it in the new bucket (matching the new hashCode() ), and won't find it there. 由于HashMap首先找到与某个键的hashCode()相匹配的存储桶,并且仅在以后检查该存储桶中所有键的键是否相等,如果给定键的hashCode()已更改,则第二次调用put将尝试在其中找到它。新存储桶(与新的hashCode()匹配),并且在那里找不到它。 Therefore the same key is added twice. 因此,相同的密钥被添加两次。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM