【面試普通人VS高手系列】HashMap是怎麼解決雜湊衝突的?

跟著Mic學架構發表於2022-04-15

常用資料結構基本上是面試必問的問題,比如HashMap、LinkList、ConcurrentHashMap等。

關於HashMap,有個學員私信了我一個面試題說: “HashMap是怎麼解決雜湊衝突的?”

關於這個問題,我們來模擬一下普通人和高手對於這個問題的回答。

普通人:

嗯.... HashMap我好久之前看過它的原始碼,我記得好像是通過連結串列來解決的!

高手:

嗯,這個問題我從四個方面來回答。

1.要了解Hash衝突,那首先我們要先了解Hash演算法和Hash表。

img

點選並拖拽以移動

(1)Hash演算法,就是把任意長度的輸入,通過雜湊演算法,變成固定長度的輸出,這個輸出結果是雜湊值。

(2)Hash表又叫做“雜湊表”,它是通過key直接訪問在記憶體儲存位置的資料結構,在具體實現上,我們通過hash函式把key對映到表中的某個位置,來獲取這個位置的資料,從而加快查詢速度。

2.所謂hash衝突,是由於雜湊演算法被計算的資料是無限的,而計算後的結果範圍有限,所以總會存在不同的資料經過計算後得到的值相同,這就是雜湊衝突。

3.通常解決hash衝突的方法有4種。

(1)開放定址法,也稱為線性探測法,就是從發生衝突的那個位置開始,按照一定的次序從hash表中找到一個空閒的位置,然後把發生衝突的元素存入到這個空閒位置中。ThreadLocal就用到了線性探測法來解決hash衝突的。

向這樣一種情況

img

點選並拖拽以移動

在hash表索引1的位置存了一個key=name,當再次新增key=hobby時,hash計算得到的索引也是1,這個就是hash衝突。而開放定址法,就是按順序向前找到一個空閒的位置來儲存衝突的key。

(2)鏈式定址法,這是一種非常常見的方法,簡單理解就是把存在hash衝突的key,以單向連結串列的方式來儲存,比如HashMap就是採用鏈式定址法來實現的。

向這樣一種情況

img

點選並拖拽以移動

存在衝突的key直接以單向連結串列的方式進行儲存。

(3)再hash法,就是當通過某個hash函式計算的key存在衝突時,再用另外一個hash函式對這個key做hash,一直運算直到不再產生衝突。這種方式會增加計算時間,效能影響較大。

(4)建立公共溢位區, 就是把hash表分為基本表和溢位表兩個部分,凡事存在衝突的元素,一律放入到溢位表中。

4.HashMap在JDK1.8版本中,通過鏈式定址法+紅黑樹的方式來解決hash衝突問題,其中紅黑樹是為了優化Hash錶連結串列過長導致時間複雜度增加的問題。當連結串列長度大於8並且hash表的容量大於64的時候,再向連結串列中新增元素就會觸發轉化。

以上就是我對這個問題的理解!

總結

這道面試題主要考察Java基礎,面向的範圍是工作1到5年甚至5年以上。

因為集合類的物件在專案中使用頻率較高,如果對集合理解不夠深刻,容易在專案中製造隱藏的BUG。

所以,再強調一下,面試的時候,基礎是很重要的考核項!!

本期的普通人VS高手面試系列的就到這裡結束了,需要面試資料或者面試問題諮詢歡迎私信和評論區留言。

我是Mic,一個工作了14年的Java程式設計師,我們們下期再見。

相關文章