Key should not be mutated while used in the map. The Map
java doc says:
Note: great care must be exercised if
mutable objects are used as map keys.
The behavior of a map is not specified
if the value of an object is changed
in a manner that affects equals
comparisons while the object is a key
in the map. A special case of this
prohibition is that it is not
permissible for a map to contain
itself as a key. While it is
permissible for a map to contain
itself as a value, extreme caution is
advised: the equals and hashCode
methods are no longer well defined on
a such a map.
I knew this issue, but never made the test until now. I elaborate then a bit more:
Map<Set<String>, Object> map = new HashMap<Set<String>, Object>();
Set<String> key1 = new HashSet<String>();
key1.add( "hello");
Set<String> key2 = new HashSet<String>();
key2.add( "hello2");
Set<String> key2clone = new HashSet<String>();
key2clone.add( "hello2");
map.put( key1, new Object() );
map.put( key2, new Object() );
System.out.println( map.containsKey(key1)); // true
System.out.println( map.containsKey(key2)); // true
System.out.println( map.containsKey(key2clone)); // true
key2.add( "mutate" );
System.out.println( map.containsKey(key1)); // true
System.out.println( map.containsKey(key2)); // false
System.out.println( map.containsKey(key2clone)); // false (*)
key2.remove( "mutate" );
System.out.println( map.containsKey(key1)); // true
System.out.println( map.containsKey(key2)); // true
System.out.println( map.containsKey(key2clone)); // true
After key2
is mutated, the map does not contains it anymore. We could think that the map "indexes" the data when they are added and we would then expect that is still contains the key2 clone (line marked with *
). But funny enough, this is not the case .
So, as the java doc says, keys should not be mutated otherwise behavior is unspecified. Period.
I guess that's what happens in your case.