HashSet.contains(): does your busket contain something?
Posted on October 1st, 2006 in EN | 4 Comments »
When you put some good into your supermarket basket, you really suppose it will stay there, don’t you? Well, we’re living inside materialistic world. All of us, except Java programmers.
Consider the following Entity class:
public static class Entity { private String _name; private int _count; public Entity(String name, int count) { _name = name; _count = count; } public void setName(String name) { _name = name; } public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; final Entity entity = (Entity) o; if (_count != entity._count) return false; if (_name != null ? !_name.equals(entity._name) : entity._name != null) return false; return true; } public int hashCode() { int result; result = (_name != null ? _name.hashCode() : 0); result = 29 * result + _count; return result; } }
Let’s store our entity into various Java collections instances, both implementing Set interface:
Set<Entity> hashSet = new HashSet<Entity>(); Set<Entity> arraySet = new CopyOnWriteArraySet<Entity>(); Entity e = new Entity(�OldName�, 5); hashSet.add(e); arraySet.add(e);
Now, let’s see whenever the previously stored entity is still inside the collections:
// returns true System.out.println(arraySet.contains(e)); // returns true System.out.println(hashSet.contains(e));
Now, a simple mutation, changing an entity name:
e.setName(�NewName�);
And, voila � now the entity is still in ArraySet, but not in TreeSet:
// returns true System.out.println(arraySet.contains(e)); // returns false System.out.println(hashSet.contains(e));
This looks like a quite stupid bug from the first time, but googling aroung brings an answer: TreeSet implementation uses hashCode() and not equals() for storing and retrieving entities, thus TreeSet requires hashCode() of contained entity to be immutable!
Presonally I think it’s too smart to be good, but, let’s say “the big brother knows beter”. The really annoying thing is that the request for proper documentation of this feature was initially issued for Java 1.3.1 at 16 May, 2001 and nothing was done since that.
Shame on you, Sun Microsystems…
