HashMap與Hashtable
HashMap與Hashtable數據結構幾乎是相同的(數組+鏈表),核心方法的實現也大致相同
主要討論不同,比較兩者不同從JDK源碼入手
一、父類不同
HashMap父類AbstractMap
Hashtable父類Dictionary
Dictionary類源碼已註釋被棄用
Hashtable類源碼註釋也表明Hashtable已被淘汰
* Java Collections Framework</a>. Unlike the new collection * implementations, {@code Hashtable} is synchronized. If a* thread-safe implementation is not needed, it is recommended to use * {@link HashMap} in place of {@code Hashtable}. If a thread-safe * highly-concurrent implementation is desired, then it is recommended * to use {@link java.util.concurrent.ConcurrentHashMap} in place of * {@code Hashtable}.
// 如果你不需要線程安全,那麽使用HashMap,如果需要線程安全,那麽使用ConcurrentHashMap。HashTable已經被淘汰了,不要在新的代碼中再使用它。
二、Synchronize
Hashtable是線程安全的,它的每個方法中都加入了Synchronize方法。
HashMap不是線程安全的,在多線程並發的環境下,使用HashMap時就必須要自己增加同步處理。
(雖然HashMap不是線程安全的,但是它的效率會比Hashtable要好很多。這樣設計是合理的。在我們的日常使用當中,大部分時間是單線程操作的。HashMap把這部分操作解放出來了。當需要多線程操作的時候可以使用線程安全的ConcurrentHashMap。ConcurrentHashMap雖然也是線程安全的,但是它的效率比Hashtable要高好多倍。因為ConcurrentHashMap使用了分段鎖,並不對整個數據進行鎖定。)
三、初始容量和擴充容量
HashMap初始容量16,擴容默認為原來容量的2倍
Hashtable初始容量11,擴容默認為原來容量的2倍+1
四、hash值算法不同
HashMap: 具體原因可參考JDK源碼學習筆記——HashMap
1.int hash = (h = key.hashCode()) ^ (h >>> 16) ;
2.int index = (table.length - 1) & hash;
3.tableSizeFor()方法保證數組容量一定是2的次冪
Hashtable:
1.int hash = key.hashCode();
2.int index = (hash & 0x7FFFFFFF) % tab.length;
五、put時的不同
1、HashMap支持key==null value==null,hash方法專門有對key==null的處理
static final int hash(Object key) { int h; return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16); }
Hashtable不支持null
public synchronized V put(K key, V value) { // Make sure the value is not null if (value == null) {// value==null拋異常 throw new NullPointerException(); } // Makes sure the key is not already in the hashtable. Entry<?,?> tab[] = table; int hash = key.hashCode();// key==null拋異常 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; }
2、JDK1.8 HashMap引入了紅黑樹,鏈表超過最大長度(8),將鏈表改為紅黑樹再添加元素
3、hash碰撞之後的處理
HashMap:在鏈表尾加入元素
Hashtable:在鏈表頭加入元素
參考資料:
HashMap 和 HashTable 到底哪不同 ?
HashMap 與HashTable的區別
HashMap與Hashtable