Reputation: 65
I have an Employee class as below.
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.
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
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. Keys must be unique in map, right? Then why I am getting same object key twice? Thanks!
Upvotes: 2
Views: 805
Reputation: 393811
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
.
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".
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".
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. Therefore the same key is added twice.
Upvotes: 5