1. 程式人生 > >HashMap和HashTable的理解與區別

HashMap和HashTable的理解與區別

   Hashtable是java一開始釋出時就提供的鍵值對映的資料結構,而HashMap產生於JDK1.2。雖然Hashtable比HashMap出現的早一些,但是現在Hashtable基本上已經被棄用了。而HashMap已經成為應用最為廣泛的一種資料型別了。造成這樣的原因一方面是因為Hashtable是執行緒安全的,效率比較低。也可能是Hashtable開始設計的時候沒有遵循駝峰命名法(手動笑哭)。

1、父類不同:

     HashMap是繼承自AbstractMap類,而HashTable是繼承自Dictionary(已被廢棄,詳情看原始碼)。不過它們都實現了同時實現了map、Cloneable(可複製)、Serializable(可序列化)這三個介面。

    Hashtable比HashMap多提供了elments() 和contains() 兩個方法。

    elments() 方法繼承自Hashtable的父類Dictionnary。elements() 方法用於返回此Hashtable中的value的列舉。

   contains()方法判斷該Hashtable是否包含傳入的value。它的作用與containsValue()一致。事實上,contansValue() 就只是呼叫了一下contains() 方法。

2、null值問題

Hashtable既不支援Null key也不支援Null value。Hashtable的put()方法的註釋中有說明 。

HashMap中,null可以作為鍵,這樣的鍵只有一個;可以有一個或多個鍵所對應的值為null。當get()方法返回null值時,可能是 HashMap中沒有該鍵,也可能使該鍵所對應的值為null。因此,在HashMap中不能由get()方法來判斷HashMap中是否存在某個鍵, 而應該用containsKey()方法來判斷。

3、執行緒安全性

Hashtable是執行緒安全的,它的每個方法中都加入了Synchronize方法。在多執行緒併發的環境下,可以直接使用Hashtable,不需要自己為它的方法實現同步

HashMap不是執行緒安全的,在多執行緒併發的環境下,可能會產生死鎖等問題。具體的原因在下一篇文章中會詳細進行分析。使用HashMap時就必須要自己增加同步處理,

雖然HashMap不是執行緒安全的,但是它的效率會比Hashtable要好很多。這樣設計是合理的。在我們的日常使用當中,大部分時間是單執行緒操作的。HashMap把這部分操作解放出來了。當需要多執行緒操作的時候可以使用執行緒安全的ConcurrentHashMap。ConcurrentHashMap雖然也是執行緒安全的,但是它的效率比Hashtable要高好多倍。因為ConcurrentHashMap使用了分段鎖,並不對整個資料進行鎖定。

tip:HashMap是JDk1.2之後有的,而在JDK1.5中,偉大的Doug Lea給我們帶來了concurrent包,從此Map也有安全的了。也就就是有了ConcurrentHashMap(關於這個的理解下次有機會再寫,或自行百度)

4、遍歷方式不同

Hashtable、HashMap都使用了Iterator。而由於歷史原因,Hashtable還使用了Enumeration的方式 。

HashMap的Iterator是fail-fast迭代器。當有其它執行緒改變了HashMap的結構(增加,刪除,修改元素),將會丟擲ConcurrentModificationException。不過,通過Iterator的remove()方法移除元素則不會丟擲ConcurrentModificationException異常。但這並不是一個一定發生的行為,要看JVM。

JDK8之前的版本中,Hashtable是沒有fast-fail機制的。在JDK8及以後的版本中 ,Hashtable也是使用fast-fail的。(此處可以去看一下1.5和1.8JDK原始碼的對比)

5、初始容量不同

Hashtable的初始長度是11,之後每次擴充容量變為之前的2n+1(n為上一次的長度)

而HashMap的初始長度為16,之後每次擴充變為原來的兩倍

建立時,如果給定了容量初始值,那麼Hashtable會直接使用你給定的大小,而HashMap會將其擴充為2的冪次方大小。

6、計算雜湊值的方法不同

為了得到元素的位置,首先需要根據元素的 KEY計算出一個hash值,然後再用這個hash值來計算得到最終的位置

Hashtable直接使用物件的hashCode。hashCode是JDK根據物件的地址或者字串或者數字算出來的int型別的數值。然後再使用除留餘數發來獲得最終的位置。 然而除法運算是非常耗費時間的。效率很低

HashMap為了提高計算效率,將雜湊表的大小固定為了2的冪,這樣在取模預算時,不需要做除法,只需要做位運算。位運算比除法的效率要高很多。