簡介之HashMap和Hashtable的區別

2022-08-24 20:42:14 字數 4140 閱讀 8708

hashmap和hashtable的區別

1.底層結構不同

1.1繼承體系的區別

hashmap是繼承自abstractmap類,而hashtable是繼承自dictionary類(注:此類已過時。新的實現應該實現 map 介面,而不是擴充套件此類)。它們都實現了同時實現了map、cloneable(可複製)、serializable(可序列化)這三個介面。

1.2內部實現使用的陣列初始化和擴容方式不同

hashtable:

(1) hashtable繼承於dictionary類,實現了map介面。map是"key-value鍵值對"介面,dictionary是宣告了操作"鍵值對"函式介面的抽象類。 

(2) hashtable是通過"拉鍊法"實現的雜湊表。它包括幾個重要的成員變數:table, count, threshold, loadfactor, modcount。

table是乙個entry陣列型別,而entry實際上就是乙個單向鍊錶。雜湊表的"key-value鍵值對"都是儲存在entry陣列中的。 

count是hashtable的大小,它是hashtable儲存的鍵值對的數量。 

threshold是hashtable的閾值,用於判斷是否需要調整hashtable的容量。threshold的值="容量*載入因子"。

loadfactor就是載入因子。 

modcount是用來實現fail-fast機制的

hashmap:

(1) hashmap內儲存資料的entry陣列預設是16,如果沒有對entry擴容機制的話,當儲存的資料一多,entry內部的鍊錶會很長,這就失去了hashmap的儲存意義了。所以hasnmap內部有自己的擴容機制。hashmap內部有:

變數size,它記錄hashmap的底層陣列中已用槽的數量;

變數threshold,它是hashmap的閾值,用於判斷是否需要調整hashmap的容量(threshold = 容量*載入因子) 

變數default_load_factor = 0.75f,預設載入因子為0.75

hashmap擴容的條件是:當size大於threshold時,對hashmap進行擴容

​   hashtable在不指定容量的情況下的預設容量為11,而hashmap為16,hashtable不要求底層陣列的容量一定要為2的整數次冪,而hashmap則要求一定為2的整數次冪。​      

hashtable擴容時,將容量變為原來的2倍加1,而hashmap擴容時,將容量變為原來的2倍。

2. 執行緒安全性的不同

(1)hashtable是執行緒安全的,hashmap是執行緒非安全的。hashtable的方法是synchronized的,而hashmap不是。

hashmap是hashtable的輕量級實現(非執行緒安全的實現)。

synchronized意味著在一次僅有乙個執行緒能夠更改hashtable。就是說任何執行緒要更新hashtable時要首先獲得同步鎖,其它執行緒要等到同步鎖被釋放之後才能再次獲得同步鎖更新hashtable。

​(2)hashmap執行效率高:執行緒非安全,計算hash值的方式更快,擴容直接*2(位運算<<1)

hashtable執行效率低:執行緒安全,計算hash值速度慢,擴容方式需要的時間相對長。

​(3)hashmap就是為了提高執行速度設計的,相對於hashtable而言,其計算hash值更容易產生「碰撞」現象,hashmap產生碰撞就以鍊錶結構儲存。hashmap的預設空間較大,時間換空間,都是在提高效率。

(4)在單執行緒環境時hashmap效率更高,在多執行緒中hashtable能避免死鎖,但是jdk1.5新增了concurrent包,引入執行緒安全的concurrenthashmap,使得map也可以執行緒安全。它引入了乙個「分段鎖」的概念,不是所有方法都是同步的,因此效率相比hashtable更高。所以儘管hashmap和hashtable非常相似,但現在hashtable已經很少用了(何況它還不符合駝峰命名規則)。

3. 對null的儲存支援不同

hashmap允許儲存1個null鍵和多個null值

hashtable不允許儲存null鍵和null值

1      public synchronized v put(k key, v value)

6 7         // makes sure the key is not already in the hashtable.

8         entry,?> tab = table;

9         int hash = key.hashcode();

10         int index = (hash & 0x7fffffff) % tab.length;

11         @suppresswarnings("unchecked")

12         entryentry = (entry)tab[index];

13         for(; entry != null ; entry = entry.next)

19         }

20 21         addentry(hash, key, value, index);

22         return null;

23     }

根據上面的部分hashtable原始碼,可以看出value==null時會丟擲異常。在key.hashcode();中如果key為null也會丟擲異常。

4.遍歷方式的內部實現上不同

(1)hashtable、hashmap都使用了 iterator。而由於歷史原因,hashtable還使用了enumeration的方式 。

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

(3)jdk8之前的版本中,hashtable是沒有fast-fail機制的。在jdk8及以後的版本中 ,hashtable也是使用fast-fail的

5.計算hash值的方法不同

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

​hashtable直接使用物件的hashcode。hashcode是jdk根據物件的位址或者字串或者數字算出來的int型別的數值。然後再使用除留餘數發來獲得最終的位置。 

​hashtable在計算元素的位置時需要進行一次除法運算,而除法運算是比較耗時的。 

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

​hashmap的效率雖然提高了,但是hash衝突卻也增加了。因為它得出的hash值的低位相同的概率比較高

為了解決這個問題,hashmap重新根據hashcode計算hash值後,又對hash值做了一些運算來打散資料。使得取得的位置更加分散,從而減少了hash衝突。當然了,為了高效,hashmap只做了一些簡單的位處理。從而不至於把使用2 的冪次方帶來的效率提公升給抵消掉。

6.小結

(1)基類不同:hashtable基於dictionary類,而hashmap是基於abstractmap。dictionary是什麼?它是任何可將鍵對映到相應值的類的抽象父類,而abstractmap是基於map介面的骨幹實現,它以最大限度地減少實現此介面所需的工作。

(2)執行緒安全:hashmap時單執行緒安全的,hashtable是多執行緒安全的。

(3)null不同:hashmap可以允許存在乙個為null的key和任意個為null的value,但是hashtable中的key和value都不允許為null。

(4)遍歷不同:hashmap僅支援iterator的遍歷方式,hashtable支援iterator和enumeration兩種遍歷方式。

(5)hash值計算方法不同,hashmap效率更高。

(6)hashtable:jdk1.0開始。執行緒安全,效率低。不允許null鍵和null值

​     hashmap:jdk1.2開始。執行緒不安全,效率高。允許null鍵和null值

Java之HashMap集合簡介及遍歷

hashmap集合是乙個比較特殊的集合,它整合了arraylist和linkedlist的特點。arraylist的優點是索引快,linkedlist的優點是插入或刪除方便,而hashmap則是由他們兩個的優點整合而來。hashmap是由乙個陣列和鍊錶組成,用陣列來儲存鍊錶的首位址,從而來達到他們兩...

HashMap中的hash演算法總結

演算法一直是我的弱項,然而面試中基本是必考的專案,剛好上次看到乙個hashmap的面試題,今天也來學習下 hashmap中的hash演算法是如何實現的。數學知識回顧 hashmap中的hash演算法 首先要明白乙個概念,hashmap中定位到桶的位置 是根據key的hash值與陣列的長度取模來計算的...

HASHMAP解決hash碰撞相關問題

1.封裝類作為key,都是final型別保證hash值不可更改 內部已經實現equals和hashcode方法,遵循hashmap內部規範計算準確性,有效減少hash碰撞的機率,2.如果使用object作為key,需要重寫equals和hashcode方法,equals保證key在hash表中唯一,...