How to lose a Java object in a Collection (Set)

I was a little careless the other day, I lost one of my business objects in a Collection!

Or to be more precise a Java business object that I had placed in a Set could only be found by iterating through the contents of the Set, if I asked the contains(Object) method to find the object that I just added but it couldn't find it. Now the clue that I should have spotted sooner was that the rather plain add(Object) method I was calling was in fact on another application class and not directly on the Set.

What was happening was this other add(Object) was adding the object to the Set and then was adding the Set into the business object (it was doing this correctly as we wanted a parent-child relationship so that each knew about the other). The problem was that the hashCode method of the business object used it's reference to the Set to compute it's value.

When the object was added to the Set hashCode produced one value, once the Set was linked to the object, hashCode produced a different value. Because contains uses the object's hashCode to try and find the object in the Set it couldn't find it.

Swapping the order of events, i.e. link the Set first then add it to the parent Set ensured that the hashCode value was consistent and now the object could always be found.

So the moral of this story: be very careful when writing hashCode & equals methods and make sure you stop messing with the object the moment you add it to the Collection.

Technorati Tags: , , , ,

1 comment:

Rob Baillie said...

Forgive me, I'm not a Java developer (besides the odd bit of Eclipse editor work).

So, because the state of the member changed, its hashcode changed, and the Set didn't automacially update to reflect that fact?

Doesn't this cause problems all over the place; doesn't this mean that objects added to collections that use the return from hashcode as their key must immediately beome read-only?

That sounds a tad restrictive - so I presume my understanding may be wrong...