Both ConcurrentHashmap and Hashtable are key value storage structures, but they have one difference: ConcurrentHashmap and Hashtable do not support key or value is null, while HashMap does. Why is there such a difference? What is the purpose of the design?
Concurrent HashMap and Hashtable both support concurrency, so there will be a problem. When you get the corresponding value through get(k), if you get null, you cannot judge whether it is null when put (k,v), or whether the key has never been mapped. HashMap is non concurrent. You can use contains(key) to make this judgment. The maps that support concurrency call m.contains(key) and m.get (key). M may be different.
HashMap.class:
// Calculation here key Of hash Value, whether it is null,If yes, returns 0, that is key by null Key value pairs // Of hash It is 0. So a hashmap Object stores only one key by null Because of their hash The values are the same. static final int hash(Object key) { int h; return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16); } // Place key value pairs in table Medium, no verification value Whether it is null. So a hashmap Objects can store // Multiple value by null Key value pairs public V put(K key, V value) { return putVal(hash(key), key, value, false, true); } final V putVal(int hash, K key, V value, boolean onlyIfAbsent, boolean evict) { Node<K,V>[] tab; Node<K,V> p; int n, i; if ((tab = table) == null || (n = tab.length) == 0) n = (tab = resize()).length; if ((p = tab[i = (n - 1) & hash]) == null) tab[i] = newNode(hash, key, value, null); else { Node<K,V> e; K k; if (p.hash == hash && ((k = p.key) == key || (key != null && key.equals(k)))) e = p; else if (p instanceof TreeNode) e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value); else { for (int binCount = 0; ; ++binCount) { if ((e = p.next) == null) { p.next = newNode(hash, key, value, null); if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st treeifyBin(tab, hash); break; } if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k)))) break; p = e; } } if (e != null) { // existing mapping for key V oldValue = e.value; if (!onlyIfAbsent || oldValue == null) e.value = value; afterNodeAccess(e); return oldValue; } } ++modCount; if (++size > threshold) resize(); afterNodeInsertion(evict); return null; }
Hashtable.class:
public synchronized V put(K key, V value) { // ensure value Not empty. This code filters all value by null Key value pair for. therefore Hashtable Can not // storage value by null Key value pairs if (value == null) { throw new NullPointerException(); } // ensure key stay table Array does not exist. Entry<?,?> tab[] = table; int hash = key.hashCode(); //Calculate here key Of hash Value, if here key by null,A null pointer exception is thrown directly. int index = (hash & 0x7FFFFFFF) % tab.length; @SuppressWarnings("unchecked") Entry<K,V> entry = (Entry<K,V>)tab[index]; for(; entry != null ; entry = entry.next) { if ((entry.hash == hash) && entry.key.equals(key)) { V old = entry.value; entry.value = value; return old; } } addEntry(hash, key, value, index); return null; }