Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Workaround for hash for a HashSet when the internal object changes

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?

like image 397
AHungerArtist Avatar asked Jan 10 '12 15:01

AHungerArtist


People also ask

Can you hash a HashSet?

Of course it has, and it can! In fact, hash keys is all the HashSet has -- just keys, no values. In a HashMap the "value" is passive: that's something stored at the key; hash maps never look at values; in particular, maps never check values for equality, or compute their hash code.

How does a HashSet avoid duplicate elements How does it work internally?

add) hash (derived from hashcode) is equal to already stored element in the HashMap and it is equal to already stored element or equals method if called on two returns true, the object will not be stored into the HashSet or the key will not be stored into the HashMap.

How HashSet works internally stack overflow?

HashSet is backed by a HashMap internally, but the element you are adding to the HashSet is used as the key in the backing HashMap . For the value, a dummy value is used. Therefore the HashSet 's contains(element) simply calls the backing HashMap 's containsKey(element) .

How does HashSet use hashing?

HashSet extends AbstractSet and implements the Set interface. It creates a collection that uses a hash table for storage. A hash table stores information by using a mechanism called hashing. In hashing, the informational content of a key is used to determine a unique value, called its hash code.


4 Answers

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.

like image 178
NPE Avatar answered Sep 20 '22 19:09

NPE


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.

like image 33
Mark Peters Avatar answered Sep 23 '22 19:09

Mark Peters


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.

like image 35
Ernest Friedman-Hill Avatar answered Sep 19 '22 19:09

Ernest Friedman-Hill


Use HashMap instead of HashSet. Define key as something unique that willn't change in the time.

like image 28
alexsmail Avatar answered Sep 20 '22 19:09

alexsmail