Is there any good advice how to deal with mutable objects that are stored in Sets?
Some objects may define their equality (and hashCode) based on their internal state. When such objects are stored in Sets, in- or outside the controlled code, a mutation of the state may lead to inconsistency in the Set.
Is there any “best-practice” to avoid or deal with that, aside don’t do it?
Example code:
static class A {
String s;
public boolean equals(Object o) {
return s.equals(((A)o).s);
}
public int hashCode() {
return s.hashCode();
}
public String toString() {
return s;
}
}
public static void main(String[] args) {
A a0 = new A();
a0.s = "Hello";
A a1 = new A();
a1.s = "World";
HashSet<A> set = new HashSet<A>();
set.add(a0);
set.add(a1);
System.out.println(set);
a0.s = "World";
System.out.println(set);
}
At some point the development team got this problem a lot when working with collections of entities that only got their key before being stored to the database. Their hashcode/equals depended on that key…
The solution we came up with was something along these lines:
Another idea was a Set implementation decorating a HashSet, but we quickly decided this would cause more problems on the long run. For the most part the above method is executed by ‘framework’ code transparently to the developer, but I am still not particularly happy with this solution.