Hash - when add key-value pair to a hashMap why Java makes hashMap39s hashCode change

De openkb
Aller à : Navigation, rechercher

Sommaire

Questions

If you look at java s hashCode method inside hashMap, you will find:

public int hashCode() {
    int h = 0;
    Iterator<Entry<K,V>> i = entrySet().iterator();
    while (i.hasNext())
        h += i.next().hashCode();
    return h;
}

So when you insert things into hashMap, hashMap s hashCode will change. Thus, if we insert an empty hashMap into hashSet, then insert something to this hashMap, then call hashSet.contains(hashMap), it will return false. Why Java allow such behavior? This will easily cause duplicate items in a hashSet.

Try run the following code:

   import java.util.HashMap;
   import java.util.HashSet;
   import java.util.Iterator;
   import java.util.Map;
public class Main {

public static void main(String[] args) {

    HashSet<HashMap<Integer, String>> set = new HashSet<>();
    HashMap<Integer, String> b = new HashMap<>();
    System.out.println("adding hashcode: " + b.hashCode() + "to set");
    set.add(b);
    b.put(8, "arsenal");
    for(HashMap<Integer, String> map: set){
        Iterator it = map.entrySet().iterator();
        while (it.hasNext()) {
            Map.Entry pair = (Map.Entry)it.next();
            System.out.println(pair.getKey() + " = " + pair.getValue());
        }
    }
    System.out.println("Finding b: " + set.contains(b));
    System.out.println(b.hashCode());

    set.add(b);

    for(HashMap<Integer, String> map: set){
        Iterator it = map.entrySet().iterator();
        while (it.hasNext()) {
            Map.Entry pair = (Map.Entry)it.next();
            System.out.println(pair.getKey() + " = " + pair.getValue());
        }
    }

}
}

Answers

Why Java allow such behavior?

Because keys are supposed to be invariant, according to their equals() implementation. If you mutate a key in such a way that comparisons by means of its equals() method are affected, then the behaviour of the map is unspecified.

And this is exactly what you re doing when you change your HashMap while it s an element of the HashSet, since HashSet is actually backed by a HashMap.

https://docs.oracle.com/javase/8/docs/api/java/util/Map.html https://docs.oracle.com/javase/8/docs/api/java/util/Map.html

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 such a map.

If I were you, I wouldn t use a mutable map as the key of a structure that relies on the immutability of its elements.

Source

License : cc by-sa 3.0

http://stackoverflow.com/questions/32556185/when-add-key-value-pair-to-a-hashmap-why-java-makes-hashmaps-hashcode-change

Related

Outils personnels
Espaces de noms

Variantes
Actions
Navigation
Outils