I have the following code
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
public class Person {
private String name;
private long birthTime;
@Override
public int hashCode() {
return Objects.hash(name, birthTime);
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof Person)) {
return false;
}
Person other = (Person) obj;
return Objects.equals(name, other.name)
&& birthTime == other.birthTime;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public long getBirthTime() {
return birthTime;
}
public void setBirthTime(long birthTime) {
this.birthTime = birthTime;
}
public static Person person(String name, long time) {
Person p = new Person();
p.setName(name);
p.setBirthTime(time);
return p;
}
public static void main(String[] args) {
Map<Person, Person> map = new HashMap<>();
Person p = person("alice", 3);
System.out.println("1. " + map.containsKey(p));
map.put(p, p);
System.out.println("2. " + map.containsKey(p));
p.setName("charlie");
System.out.println("3. " + map.containsKey(p));
Person p2 = person("alice", 3);
System.out.println("4. " + map.containsKey(p2));
Person p3 = person("charlie", 3);
System.out.println("5. " + map.containsKey(p3));
}
}
I am expecting the output to be false, true, true, false and true. However, the output is false, true, false, false, false.
I am looking for how the output is false for the 3rd and 5th case. What is the behavior of HashMap containsKey?
Why is the output false even though the Key object is there in the Map. The equals and hashcode methods are both overridden for the Person class.
The following statement breaks your Map:
It causes the key referenced by the variable
p
to no longer be positioned in the bin that matches itshashCode()
, since you are changing itshashCode()
.You should never change the state of a key that is already in the Map if that change affects the result of
hashCode()
orequals()
.Returns
false
since aPerson
instance whose name is "charlie" is not mapped to the same bin as aPerson
instance whose name is "alice". ThereforecontainsKey()
searches forp
in the bin matching the name "charlie", and doesn't find it there.Returns
false
sincep2
is not equal top
(they have different names).Returns
false
since the keyp
is located in the bin that matches the name "alice", even though its current name is "charlie", socontainsKey()
searches for it in the wrong bin, and doesn't find it.