Should hashCode() only use the subset of immutable fields of those used in equals()?

Viewed 1297

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

  • mutable fields are needed to correctly implement equals()
  • use these objects safely in hash-based Collections or Maps such ash HashSet even if they are prone to changes.

which conflicts with the convention that

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

  • the contract is fullfilled: equal objects will produce the same hashCode, while the same hashCode does not necesairly mean that the objects are the same.
  • The hashCode of an object stays the same, even if an object is exposed to changes and therefore will be found in a 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

4 Answers
Related