1. 程式人生 > >HashMap與Hashtable

HashMap與Hashtable

res 多線程並發 url tro read 個數 code rec .com

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