Situation
I needed to overwrite equals()
and as it is recommended I also overwrote the hashCode()
method using the same fields. Then, when I was looking at a set, that contained only the one object I got the frustrating result of
set.contains(object)
=> false
while
set.stream().findFirst().get().equals(object)
=> true
I understand now, that this is due to changes that were made to object
after it was added to set
which again changed its hashCode. contains
then looks at the wrong key and can't find the object
.
My requirements for the implementation are
equals()
Collections
or Maps
such ash HashSet
even if they are prone to changes.which conflicts with the convention that
equals()
and hashCode()
should use the same fields in order to avoid surprises (as argued here: https://stackoverflow.com/a/22827702).Question
Are there any dangers to using only a subset of fields which are used in equals()
to calculate hashCode()
instead of using all?
More specifically this would mean: equals()
uses a number of fields of the object whereas hashCode()
only uses those fields that are used in equals()
and that are immutable.
I think this should be okay, because
HashSet
before and after those changes.Related posts that helped me understand my problem but not how to solve it: What issues should be considered when overriding equals and hashCode in Java? and Different fields for equals and hashcode
It's ok for hashCode()
to use a subset of the fields that equals()
uses, although it may possibly give you a slight performance drop.
Your problem seems to be caused by modifying the object, while still inside the set, in a way that alters the functioning of hashCode()
and/or equals()
. Whenever you add an object to a HashSet (or as the key in a HashMap), you must not subsequently modify any fields of that object that are used by equals()
and/or hashCode()
. Ideally, all fields used by equals()
should be final
. If they can't be, you must treat them as though they are final whilst the object is in the set.
The same goes for TreeSet/TreeMap, too, but applies to fields used by compareTo()
.
If you really need to modify the fields that are used by equals()
(or by compareTo()
in the case of a TreeSet/TreeMap), you must:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With