"Contains" an ArrayList vs HashSet implementation
I have a HashSet<Foo>
. I have an object that
- equal to the element of the collection, and
- has a corresponding hash code for the same implementation object.
However, if I call hashSet.contains(fooInstance)
, it returns false
.
Where it is really strange that the following line returns true
:
new ArrayList<Foo>(hashSet).contains(fooInstance)
Unfortunately, it turned out to be harder than expected to figure out exactly where the difference in the implementation of .contains()
. But I thought I would be safe, since .equals()
and .hashCode()
work fine.
The most likely reason is that hashCode
of Foo
unstable and that the hashCode()
return value of the Foo
instance has changed since it was added to the HashSet
. Ideally, you would only add immutable objects to a HashSet
.
For performance reasons, the HashSet
stores the calculated hashCode
in its record, so it does not need to re-read it for each get
. Therefore, if an object is modified inside a HashSet
, it will not be implemented, and your object will be effectively "lost" in the HashSet
(you can still get it by iterating through all the elements, which is essentially what copying is in an ArrayList
).