Sam Newman's site, a Consultant at ThoughtWorks

I found an interesting bug in my code today. I’m storing an object in a cache, and using a couple of indexes to address it. One index is a normal HashMap object, which is indexing the object based on its unique ID. The other index is applying a grouping – several objects with the same grouping could exists so here I use a HashMap indexing a HashSet object. When I need to update the object, I call put on the ID index, which updates the entry. For the grouping index, I get the HashSet and call add. I noticed that the unique ID index was updating, but the grouping index wasn’t – I had of course failed to read the documentation for HashSet‘s add method:

Adds the specified element to this set if it is not already present.

This contrasts with the HashMap‘s put method:

Associates the specified value with the specified key in this map. If the map previously contained a mapping for this key, the old value is replaced.

Now I should of read the documentation, but the reason for my mistake is that I knew that a HashSet was actually backed by a HashMap – as such I assumed add would just call put on the underlying HashMap using the same object as a key and the value. Of course I am misusing a Set here – a Set is a collection of objects with no duplicates. When calling add equals is called, shows that the object is already there, and therefore doesn’t re-add it. Really I want the behaviour of a Map with the simpler interface of a Set, so I should just stop complaining and write my own wrapper class, shouldn’t I?

3 Responses to “Of HashSets and HashMaps”

  1. Nipsu

    There’s no such thing as previous value for Set. It doesn’t make any sense to return ‘previous’ value from set since if there was a ‘previous’ value it’s ‘logically’ the same object that you are trying to insert.

  2. Sam Newman

    Cameron, yes I could use a HashMap, but I’d probably wrap it to simplify the put method – the key and value will always be the same, and there are some other features (logging) that mcould be integrated into the class. I’d probably reuse this anyway, given the number of data strcutures I’ve got flying around right now.
    Nipsu, that was kind of the point I was trying to make – I was annoyed initially for what appeared to be inconsistancies in the API’s between HashSet and HashMap, and then realised I was fundamentally misusing a Set.


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

Basic HTML is allowed. Your email address will not be published.

Subscribe to this comment feed via RSS

%d bloggers like this: