Reputation: 9609
The answer to this SO explains the issue I'm having: HashSet.remove() and Iterator.remove() not working
Basically, once I add something to the HashSet, if I modify any of its fields, then the set will fail any equality tests with a set containing an object with the exact same fields, since the hash code it was stored in was for when it had different fields set.
So, since that answer explains what's going on, what would be a good workaround for this to have both the uniqueness of using a set and be able to modify internal fields of the objects in the set? Or is this just not possible?
Upvotes: 8
Views: 2113
Reputation: 10122
Use any other collection (maybe a LinkedList
), and check for uniqueness only at the moment of adding, like in
public class MySetList<E> extends LinkedList<E> implements Set<E> {
private static final long serialVersionUID = 1L;
@Override
public boolean add(E e) {
return new HashSet<E>(this).add(e) ? super.add(e) : false;
}
}
Upvotes: -1
Reputation: 500923
If the fields that you modify are not part of the equality test, they should not be part of the hash code computation either. In that case there's no problem: you can just modify those fields.
If the fields are part of the equality test, the cleanest way is probably to remove the object from the set, then modify and re-insert it.
If it's the latter, and you find yourself doing this a lot, you might want to re-visit the choice of data structure for the problem at hand.
Upvotes: 8
Reputation: 5813
Use HashMap instead of HashSet. Define key as something unique that willn't change in the time.
Upvotes: 1
Reputation: 81724
The only way to work around it would be to not have a hashCode()
method that depends on any mutable fields. If objects have an identity and existence that's independent of the values of its fields, then this is easy -- use System.identityHashCode()
. Otherwise, you might base the hashCode()
on one single non-mutable field. If there isn't one, then I'm afraid you're out of luck.
Upvotes: 3
Reputation: 81164
Remove the object you want to modify from the set, change it, and then add it back. As far as I know there is no standard Set
implementation that can cope with fields (that are used in either the hashCode()
or compareTo()
implementation) being changed while it is stored.
Alternatively, if the fields aren't used in determining identity, equality or location (i.e. not used in hashCode()
, compareTo
or equals()
) then there is no problem.
Upvotes: 7