HashMap、HashTable 和 ConcurrentHashMap 的键值对<K,V>能否为null

来源:互联网 发布:dijkstra算法c语言 编辑:程序博客网 时间:2024/06/07 14:25

本文目录

  • 本文目录
  • 已有结论
    • HashMap的put源码
    • HashTable的put源码
    • ConcurrentHashMap的put源码

已有结论

  • HashMap可以允许插入null keynull value
  • HashTableConcurrentHashMap都不可以插入null keynull value

HashMapput源码:

  /**     * Associates the specified value with the specified key in this map.     * If the map previously contained a mapping for the key, the old value is replaced.     */    public V put(K key, V value) {        if (table == EMPTY_TABLE) {            inflateTable(threshold);        }        if (key == null)            return putForNullKey(value);        int hash = hash(key);        int i = indexFor(hash, table.length);        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))) {                V oldValue = e.value;                e.value = value;                e.recordAccess(this);                return oldValue;            }        }        modCount++;        addEntry(hash, key, value, i);        return null;    }
  /**     * Offloaded version of put for null keys     */    private V putForNullKey(V value) {        for (Entry<K,V> e = table[0]; e != null; e = e.next) {            if (e.key == null) {                V oldValue = e.value;                e.value = value;                e.recordAccess(this);                return oldValue;            }        }        modCount++;        addEntry(0, null, value, 0);        return null;    }

可以看到 null key的情况,调用putForNullKey方法, 可以看到null key 元素被放在了第0个位置了, 如果第0个位置为空——直接赋值第0个位置, 否则, 在第0个位置产生一个链表,addEntry(0, null, value, 0);


HashTableput源码:

public synchronized V put(K key, V value) {         // Make sure the value is not null        if (value == null) {             throw new NullPointerException();         }         // Makes sure the key is not already in the hashtable.         Entry tab[] = table;        int hash = hash(key);         int index = (hash & 0x7FFFFFFF) % tab.length;         for (Entry<K,V> e = tab[index] ; e != null ; e = e.next) {             if ((e.hash == hash) && e.key.equals(key)) {                 V old = e.value;                 e.value = value;                 return old;             }         }         modCount++;         if (count >= threshold) {             // Rehash the table if the threshold is exceeded             rehash();             tab = table;             hash = hash(key);             index = (hash & 0x7FFFFFFF) % tab.length;         }         // Creates the new entry.         Entry<K,V> e = tab[index];         tab[index] = new Entry<>(hash, key, value, e);         count++;         return null;     }  

源码中判断了null value的情况,null value就抛出空指针异常异常
但是我们并没有看到判断null key然后抛出异常的语句,那么继续看看hash方法的源码就明白了:

private int hash(Object k) {          // hashSeed will be zero if alternative hashing is disabled.          return hashSeed ^ k.hashCode();      }  

k.hashCode(),当k出入为null key 就会报错 空指针异常。


ConcurrentHashMapput源码:

public V put(K key, V value) {          Segment<K,V> s;        if (value == null)              throw new NullPointerException();        int hash = hash(key);          int j = (hash >>> segmentShift) & segmentMask;          if ((s = (Segment<K,V>)UNSAFE.getObject          // nonvolatile; recheck               (segments, (j << SSHIFT) + SBASE)) == null) //  in ensureSegment              s = ensureSegment(j);          return s.put(key, hash, value, false);      }  

null valuenull key会报错的问题和HashTable原因是一样的,hash方法:

private int hash(Object k) {         int h = hashSeed;         if ((0 != h) && (k instanceof String)) {             return sun.misc.Hashing.stringHash32((String) k);         }         h ^= k.hashCode();         // Spread bits to regularize both segment and index locations,         // using variant of single-word Wang/Jenkins hash.         h += (h <<  15) ^ 0xffffcd7d;         h ^= (h >>> 10);         h += (h <<   3);         h ^= (h >>>  6);         h += (h <<   2) + (h << 14);         return h ^ (h >>> 16);     }  
阅读全文
0 0