Hashtable是java一開始發(fā)布時就提供的鍵值映射的數(shù)據(jù)結(jié)構(gòu)度硝,而HashMap產(chǎn)生于JDK1.2。雖然Hashtable比HashMap出現(xiàn)的早一些期揪,但是現(xiàn)在Hashtable基本上已經(jīng)被棄用了悟衩。而HashMap已經(jīng)成為應(yīng)用最為廣泛的一種數(shù)據(jù)類型了。造成這樣的原因一方面是因為Hashtable是線程安全的矾飞,效率比較低一膨。也可能是Hashtable開始設(shè)計的時候沒有遵循駝峰命名法(手動笑哭)。
1洒沦、父類不同:
? ? HashMap是繼承自AbstractMap類豹绪,而HashTable是繼承自Dictionary(已被廢棄,詳情看源代碼)申眼。不過它們都實現(xiàn)了同時實現(xiàn)了map瞒津、Cloneable(可復(fù)制)、Serializable(可序列化)這三個接口括尸。
? ? Hashtable比HashMap多提供了elments() 和contains() 兩個方法巷蚪。
? ? elments() 方法繼承自Hashtable的父類Dictionnary。elements() 方法用于返回此Hashtable中的value的枚舉濒翻。
? contains()方法判斷該Hashtable是否包含傳入的value屁柏。它的作用與containsValue()一致啦膜。事實上,contansValue() 就只是調(diào)用了一下contains() 方法前联。
2功戚、null值問題
Hashtable既不支持Null key也不支持Null value。Hashtable的put()方法的注釋中有說明 似嗤。
HashMap中啸臀,null可以作為鍵,這樣的鍵只有一個烁落;可以有一個或多個鍵所對應(yīng)的值為null乘粒。當(dāng)get()方法返回null值時,可能是 HashMap中沒有該鍵伤塌,也可能使該鍵所對應(yīng)的值為null灯萍。因此,在HashMap中不能由get()方法來判斷HashMap中是否存在某個鍵每聪, 而應(yīng)該用containsKey()方法來判斷旦棉。
3、線程安全性
Hashtable是線程安全的药薯,它的每個方法中都加入了Synchronize方法绑洛。在多線程并發(fā)的環(huán)境下,可以直接使用Hashtable童本,不需要自己為它的方法實現(xiàn)同步
HashMap不是線程安全的真屯,在多線程并發(fā)的環(huán)境下,可能會產(chǎn)生死鎖等問題穷娱。具體的原因在下一篇文章中會詳細(xì)進(jìn)行分析绑蔫。使用HashMap時就必須要自己增加同步處理,
雖然HashMap不是線程安全的泵额,但是它的效率會比Hashtable要好很多配深。這樣設(shè)計是合理的。在我們的日常使用當(dāng)中嫁盲,大部分時間是單線程操作的凉馆。HashMap把這部分操作解放出來了。當(dāng)需要多線程操作的時候可以使用線程安全的ConcurrentHashMap亡资。ConcurrentHashMap雖然也是線程安全的,但是它的效率比Hashtable要高好多倍向叉。因為ConcurrentHashMap使用了分段鎖锥腻,并不對整個數(shù)據(jù)進(jìn)行鎖定。
tip:HashMap是JDk1.2之后有的母谎,而在JDK1.5中瘦黑,偉大的Doug Lea給我們帶來了concurrent包,從此Map也有安全的了。也就就是有了ConcurrentHashMap(關(guān)于這個的理解下次有機(jī)會再寫幸斥,或自行百度)
4匹摇、遍歷方式不同
Hashtable、HashMap都使用了Iterator甲葬。而由于歷史原因廊勃,Hashtable還使用了Enumeration的方式 。
HashMap的Iterator是fail-fast迭代器经窖。當(dāng)有其它線程改變了HashMap的結(jié)構(gòu)(增加坡垫,刪除,修改元素)画侣,將會拋出ConcurrentModificationException冰悠。不過,通過Iterator的remove()方法移除元素則不會拋出ConcurrentModificationException異常配乱。但這并不是一個一定發(fā)生的行為溉卓,要看JVM。
JDK8之前的版本中搬泥,Hashtable是沒有fast-fail機(jī)制的桑寨。在JDK8及以后的版本中 ,Hashtable也是使用fast-fail的佑钾。(此處可以去看一下1.5和1.8JDK源碼的對比)
5西疤、初始容量不同
Hashtable的初始長度是11,之后每次擴(kuò)充容量變?yōu)橹暗?n+1(n為上一次的長度)
而HashMap的初始長度為16休溶,之后每次擴(kuò)充變?yōu)樵瓉淼膬杀?/p>
創(chuàng)建時代赁,如果給定了容量初始值,那么Hashtable會直接使用你給定的大小兽掰,而HashMap會將其擴(kuò)充為2的冪次方大小芭碍。
6、計算哈希值的方法不同
為了得到元素的位置孽尽,首先需要根據(jù)元素的 KEY計算出一個hash值窖壕,然后再用這個hash值來計算得到最終的位置
Hashtable直接使用對象的hashCode。hashCode是JDK根據(jù)對象的地址或者字符串或者數(shù)字算出來的int類型的數(shù)值杉女。然后再使用除留余數(shù)發(fā)來獲得最終的位置瞻讽。 然而除法運算是非常耗費時間的。效率很低
HashMap為了提高計算效率熏挎,將哈希表的大小固定為了2的冪速勇,這樣在取模預(yù)算時,不需要做除法坎拐,只需要做位運算烦磁。位運算比除法的效率要高很多养匈。
---------------------
作者:藍(lán)海丶丶
來源:CSDN
原文:https://blog.csdn.net/yu849893679/article/details/81530298
版權(quán)聲明:本文為博主原創(chuàng)文章,轉(zhuǎn)載請附上博文鏈接都伪!