Java 同一对象用作映射中两个条目的键
我有一个雇员类别如下Java 同一对象用作映射中两个条目的键,java,object,hashmap,Java,Object,Hashmap,我有一个雇员类别如下 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) {
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;
}}
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());
});
我使用这个Employee类对象作为HashMap中的键,如下所示
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;
}}
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());
});
Map empMap=newhashmap();
员工e1=新员工(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(新员工(122,“xyz”));
System.out.println(empMap.get(新员工(123,“xyz”));
Set mapEmpKeys=empMap.keySet();
mapEmpKeys.forEach(emp->{
System.out.println(“员工ID:+emp.getEmpId()+”员工姓名:+emp.getEmpName());
});
程序的输出:
1.
自闭症
2.
自闭症
无效的
员工ID:122员工姓名:xyz
员工ID:122员工姓名:xyz
我的问题是,即使作为关键点的对象是相同的,我得到的地图大小为2。有人能给我解释一下,通过将Employee对象e1的id设置为不同的值,并将其再次添加到map中,将其大小设置为2,当我在map的键集上迭代时,两个条目的对象都是相同的。钥匙在地图上必须是唯一的,对吗?那为什么我会得到相同的对象键两次呢?
谢谢 当您在
HashMap
中变异用作键的实例时,如果您修改用于确定相等性或计算hashCode()
的属性,则会破坏HashMap
第一次将密钥放入映射时,它被放入与基于值123和“xyz”计算的hashCode()
相对应的bucket中
第二次在映射中放入同一个键时,它被放入另一个bucket中,该bucket与基于值122和“xyz”计算的hashCode()
相对应
由于
HashMap
首先找到与密钥的hashCode()
匹配的bucket,然后才检查该bucket中的所有密钥是否相等,因此如果给定密钥的hashCode()
已更改,则对put
的第二次调用将尝试在新bucket中找到它(匹配新的hashCode()
),在那里找不到。因此,同一个密钥被添加两次。简短回答-如果需要将其用作密钥,Employee应该是不可变的。在更改员工id之前和之后打印哈希代码。同时打印它们是否相等。只有一个Employee
对象。仅仅因为您修改了它并将其存储在地图中,并不意味着现在有两个。而且,可变键是个坏主意。