HashMap has a null key

Like HashMap internal difference between null and 0 as a key.

According to this post hash code for null key 0 , is this correct? If so, then both should go in the same bucket with index 0 and there should be one value in the HashMap , but that’s not how the HashMap works.

Can someone explain to me? what is the hash code for null in HashMap ?

Code example:

 HashMap<Integer,String> map=new HashMap<Integer,String>(); map.put(null, "abc"); map.put(0, "xyz"); // will it override the value for null as key? System.out.println(map.get(null)); // abc System.out.println(map.get(0)); // xyz 
+3
source share
4 answers

If so, then both should go in the same bucket with index 0 ...

Right.

and there must be one value in the HashMap

Wrong. For two keys there will be a shared record. This is guaranteed by the Map and HashMap specifications; those. javadocs say that for each separate key there will be a separate record. Implementation is necessary to meet the specification ... and it does.

Prior to Java 8, the way that HashMap handles collisions is to combine all hash entries into the same bucket. The logic HashMap.get(key) will HashMap.get(key) over the chain for the corresponding bucket, looking for the record corresponding to the key. (In your sample code, for null and Integer(0) chains, separate entries in the chain will be highlighted.)

In Java 8, it works the same way to begin with, but there is an optimization for the case where all keys implement Comparable and the chains get too long. In this case, long chains are converted to binary trees ... so that scanning the chain O(N) turns into a search for the tree O(logN) .

+4
source

Both cases relate to hashCode()==0 , but equals differs, therefore, in two entries, and both get return related values.

Case with zero:

 public V put(null,"abc") { if (key == null) return putForNullKey(value); } private V putForNullKey(V value) { .. addEntry(0, null, value, 0); ==> 0th index with 0 hashCode return null; } 

Case with 0:

 public V put(K key, V value) { int hash = hash(key.hashCode()); ==> 0 int i = indexFor(hash, table.length); ==> 0 for (Entry<K,V> e = table[i]; e != null; e = e.next) { Object k; if (e.hash == hash && ((k = e.key) == key || key.equals(k))) { ==> false .. } } modCount++; addEntry(hash, key, value, i); ==> addition to link list return null; } 
+1
source

You may have some hash errors.

1, when the key is 0, the hash code may not be 0. Since the hash code is:

 final int hash(Object k) { int h = hashSeed; if (0 != h && k instanceof String) { return sun.misc.Hashing.stringHash32((String) k); } h ^= k.hashCode(); h ^= (h >>> 20) ^ (h >>> 12); return h ^ (h >>> 7) ^ (h >>> 4); } 

2, when your key is zero, JDK calls a special method,

  if (key == null) return putForNullKey(value); 

Yes, when the key is zero, the hash is 0. If you want to know more, see the JDK source code.

0
source

This is possible because a single Entry in a HashMap is not just a pair of keys and values, but also has a next field, so it is a simple list of links and adding a new record looks like this:

 void createEntry(int hash, K key, V value, int bucketIndex) { Entry<K,V> e = table[bucketIndex]; table[bucketIndex] = new Entry<>(hash, key, value, e); size++; } 

e local variable (one that was already present) ends as the next value in Entry for the given hash and bucketIndex .

0
source

Source: https://habr.com/ru/post/1202986/


All Articles