JAVA面试题:HashMap和Hashtable的区别
?
HashMap和Hashtable的區別
1.共同點:都是雙列集合,底層都是哈希算法
2.區別:
* 1.HashMap是線程不安全的,效率高,JDK1.2版本
* Hashtable是線程安全的,效率低,JDK1.0版本
* 2.HashMap可以存儲null鍵和null值
* Hashtable不可以存儲null鍵和null值
3.代碼示例:
public class testHashtable {public static void main(String []args){HashMap<String,Integer> hm=new HashMap<>();hm.put(null,1);hm.put("張三",null);System.out.println(hm);Hashtable<String,Integer> ht=new Hashtable<>();ht.put(null,8);ht.put("張三",null);System.out.println(ht);} }HashMap與Hashtable的區別是面試中經常遇到的一個問題。這個問題看似簡單,但如果深究進去,也能了解到不少知識。本文對兩者從來源,特性,算法等多個方面進行對比總結。力爭多角度,全方位的展示二者的不同,做到此問題的終結版。
1 作者?
Hashtable的作者:?
?
HashMap的作者:?
Hash Map的作者比Hashtable的作者多了著名頂頂的并發大神Doug Lea。他寫了util.concurrent包。著有并發編程圣經Concurrent Programming in Java: Design Principles and Patterns 一書。他的個人主頁: http://g.oswego.edu/
Josh Bloch 為領導了眾多Java平臺特性的設計和實現,其中包括Java Collection框架、java.math包以及assert機制。著有 Effective Java 一書。
Arthur van Hoff最早任職于硅谷的Sun Microsystems公司,從事Java程序語言的早期開發工作。設計并實現了JDK 1.0的許多方面,包括Java編譯器、Java調試器、許多標準Java類以及HotJava瀏覽器。隨后創立了多家成功的企業,其中包括Marimba(1999年IPO)、Strangeberry(后被TiVo收購)、ZING(后被Dell收購)和Ellerdale(后被Flipboard收購)。Java命名來源有這么一種說法,來源于開發人員名字的組合:James Gosling、Arthur Van Hoff和Andy Bechtolsheim首字母的縮寫。
Neal Gafter是Java SE 4和5語言增強的主要設計者和實現者,他的Java閉包實現贏得了OpenJDK創新者挑戰賽的大獎。他也在繼續參與SE 7和8的語言發展。之前Neal在為Google的在線日歷工作,也曾經是C++標準委員會的一員,并曾在Sun微系統公司,MicroTec研究院和德州儀器領導開發C和C++編譯器。如今Neal在微軟開發.NET平臺編程語言。Neal是《Java Puzzlers:Traps, Pitfalls and Corner Cases》(Addison Wesley,2005)一書的合作者。他擁有羅徹斯特大學計算機科學的博士學位。
可見這些作者都是java乃至整個it領域大名鼎鼎的人物。也只有這些大師級人物才能寫出HashMap這么大道至簡的數據類型了。
2 產生時間?
Hashtable是java一開始發布時就提供的鍵值映射的數據結構,而HashMap產生于JDK1.2。雖然Hashtable比HashMap出現的早一些,但是現在Hashtable基本上已經被棄用了。而HashMap已經成為應用最為廣泛的一種數據類型了。造成這樣的原因一方面是因為Hashtable是線程安全的,效率比較低。另一方面可能是因為Hashtable沒有遵循駝峰命名法吧。。。
3 繼承的父類不同?
HashMap和Hashtable不僅作者不同,而且連父類也是不一樣的。HashMap是繼承自AbstractMap類,而HashTable是繼承自Dictionary類。不過它們都實現了同時實現了map、Cloneable(可復制)、Serializable(可序列化)這三個接口
Dictionary類是一個已經被廢棄的類(見其源碼中的注釋)。父類都被廢棄,自然而然也沒人用它的子類Hashtable了。?
* NOTE: This class is obsolete. New implementations should?
* implement the Map interface, rather than extending this class.
4 對外提供的接口不同?
Hashtable比HashMap多提供了elments() 和contains() 兩個方法。
elments() 方法繼承自Hashtable的父類Dictionnary。elements() 方法用于返回此Hashtable中的value的枚舉。
contains()方法判斷該Hashtable是否包含傳入的value。它的作用與containsValue()一致。事實上,contansValue() 就只是調用了一下contains() 方法。
5 對Null key 和Null value的支持不同?
Hashtable既不支持Null key也不支持Null value。Hashtable的put()方法的注釋中有說明。?
當key為Null時,調用put() 方法,運行到下面這一步就會拋出空指針異常。因為拿一個Null值去調用方法了。?
當value為null值時,Hashtable對其做了限制,運行到下面這步也會拋出空指針異常。?
HashMap中,null可以作為鍵,這樣的鍵只有一個;可以有一個或多個鍵所對應的值為null。當get()方法返回null值時,可能是 HashMap中沒有該鍵,也可能使該鍵所對應的值為null。因此,在HashMap中不能由get()方法來判斷HashMap中是否存在某個鍵, 而應該用containsKey()方法來判斷。
6 線程安全性不同?
Hashtable是線程安全的,它的每個方法中都加入了Synchronize方法。在多線程并發的環境下,可以直接使用Hashtable,不需要自己為它的方法實現同步
HashMap不是線程安全的,在多線程并發的環境下,可能會產生死鎖等問題。具體的原因在下一篇文章中會詳細進行分析。使用HashMap時就必須要自己增加同步處理,
雖然HashMap不是線程安全的,但是它的效率會比Hashtable要好很多。這樣設計是合理的。在我們的日常使用當中,大部分時間是單線程操作的。HashMap把這部分操作解放出來了。當需要多線程操作的時候可以使用線程安全的ConcurrentHashMap。ConcurrentHashMap雖然也是線程安全的,但是它的效率比Hashtable要高好多倍。因為ConcurrentHashMap使用了分段鎖,并不對整個數據進行鎖定。
7 遍歷方式的內部實現上不同?
Hashtable、HashMap都使用了 Iterator。而由于歷史原因,Hashtable還使用了Enumeration的方式 。
HashMap的Iterator是fail-fast迭代器。當有其它線程改變了HashMap的結構(增加,刪除,修改元素),將會拋出ConcurrentModificationException。不過,通過Iterator的remove()方法移除元素則不會拋出ConcurrentModificationException異常。但這并不是一個一定發生的行為,要看JVM。
JDK8之前的版本中,Hashtable是沒有fast-fail機制的。在JDK8及以后的版本中 ,HashTable也是使用fast-fail的, 源碼如下:?
modCount的使用類似于并發編程中的CAS(Compare and Swap)技術。我們可以看到這個方法中,每次在發生增刪改的時候都會出現modCount++的動作。而modcount可以理解為是當前hashtable的狀態。每發生一次操作,狀態就向前走一步。設置這個狀態,主要是由于hashtable等容器類在迭代時,判斷數據是否過時時使用的。盡管hashtable采用了原生的同步鎖來保護數據安全。但是在出現迭代數據的時候,則無法保證邊迭代,邊正確操作。于是使用這個值來標記狀態。一旦在迭代的過程中狀態發生了改變,則會快速拋出一個異常,終止迭代行為。
8 初始容量大小和每次擴充容量大小的不同?
Hashtable默認的初始大小為11,之后每次擴充,容量變為原來的2n+1。HashMap默認的初始化大小為16。之后每次擴充,容量變為原來的2倍。
創建時,如果給定了容量初始值,那么Hashtable會直接使用你給定的大小,而HashMap會將其擴充為2的冪次方大小。也就是說Hashtable會盡量使用素數、奇數。而HashMap則總是使用2的冪作為哈希表的大小。
之所以會有這樣的不同,是因為Hashtable和HashMap設計時的側重點不同。Hashtable的側重點是哈希的結果更加均勻,使得哈希沖突減少。當哈希表的大小為素數時,簡單的取模哈希的結果會更加均勻。而HashMap則更加關注hash的計算效率問題。在取模計算時,如果模數是2的冪,那么我們可以直接使用位運算來得到結果,效率要大大高于做除法。HashMap為了加快hash的速度,將哈希表的大小固定為了2的冪。當然這引入了哈希分布不均勻的問題,所以HashMap為解決這問題,又對hash算法做了一些改動。這從而導致了Hashtable和HashMap的計算hash值的方法不同?
9 計算hash值的方法不同?
為了得到元素的位置,首先需要根據元素的 KEY計算出一個hash值,然后再用這個hash值來計算得到最終的位置。
Hashtable直接使用對象的hashCode。hashCode是JDK根據對象的地址或者字符串或者數字算出來的int類型的數值。然后再使用除留余數發來獲得最終的位置。?
Hashtable在計算元素的位置時需要進行一次除法運算,而除法運算是比較耗時的。?
HashMap為了提高計算效率,將哈希表的大小固定為了2的冪,這樣在取模預算時,不需要做除法,只需要做位運算。位運算比除法的效率要高很多。
HashMap的效率雖然提高了,但是hash沖突卻也增加了。因為它得出的hash值的低位相同的概率比較高,而計算位運算
為了解決這個問題,HashMap重新根據hashcode計算hash值后,又對hash值做了一些運算來打散數據。使得取得的位置更加分散,從而減少了hash沖突。當然了,為了高效,HashMap只做了一些簡單的位處理。從而不至于把使用2 的冪次方帶來的效率提升給抵消掉。
總結
以上是生活随笔為你收集整理的JAVA面试题:HashMap和Hashtable的区别的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 一种改进的高光谱图像CEM目标检测算法
- 下一篇: chatbot1_2 RNN简单实现