Imagine that we have this piece of code.
public class HashAddAfter {
private class A {
public int value;
public A(int value) {
this.value = value;
}
public void setValue(int value) {
this.value = value;
}
// Code for hashCode()...
// Code for equals()...
}
Set<A> list1 = new HashSet<A>();
Set<A> list2 = new HashSet<A>();
public static void main(String[] args) {
HashAddAfter x = new HashAddAfter();
A e1 = x.new A(1);
A e2 = x.new A(1);
x.list1.add(e1);
x.list2.add(e2);
System.out.println(x.list1.equals(x.list2)); // true
e1.setValue(4);
e2.setValue(4);
System.out.println(x.list1.equals(x.list2)); // false
}
}
I didn't put the code for hashCode() and equals() due to space constraints, but it's the one generated from Eclipse.
The problem is that before changing the elements in the two sets, the sets are equal. After changing their values (each to the same value), the sets are not equal anymore, although e1.hashCode() == e2.hashCode() and e1.equals(e2).
I'm guessing that when comparing two HashSets, Java uses the original hashCode of the element (the one at the moment of insertion). So, changing the elements after insertion changes their original hashCode, and therefore contains() will return false.
In my opinion this is a very unintuitive behaviour.
What do you think?
See Question&Answers more detail:
os 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…