How to use Sets as keys in Java Maps

前端 未结 4 818
借酒劲吻你
借酒劲吻你 2020-12-06 04:58

I have a Map that uses a Set for the key type, like this:

Map, Val> map;

When I query map.containsKey(myBunchOfThing

4条回答
  •  天命终不由人
    2020-12-06 05:47

    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, Object> map  = new HashMap, Object>();
    
       Set key1 = new HashSet();
       key1.add( "hello");
    
       Set key2 = new HashSet();
       key2.add( "hello2");
    
       Set key2clone = new HashSet();
       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 contain it anymore. We could think that the map "indexes" the data when it's added and we would then expect that it 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 the behavior is unspecified. Period.

    I guess that's what happens in your case.

提交回复
热议问题