hashmap1 7以及1 8的一些理解

2021-09-27 13:53:18 字數 1441 閱讀 4079

hashmap的put操作:

根據key經過擾動函式(異或和取餘的操作)得到乙個hash值,然後根據這個hash進行hash&(n-1)得到乙個索引值,然後判斷當前索引值的陣列位置是否有有元素,如果有元素,再根據equals判斷連個元素是否相同,相同的話,則直接覆蓋當前元素,不相同的話,則產生hash衝突,採用拉鍊法解決衝突。

hashmap1.7

底層結構:陣列+鍊錶。

擴容操作:

void

transfer

(entry[

] newtable,

boolean rehash)

int i =

indexfor

(e.hash, newcapacity)

; e.next = newtable[i]

; newtable[i]

= e;

e = next;}}

}

可以看到在陣列之間的遷移過程中,鍊錶是以頭插法進行遷移的,所以遷移到新陣列後,鍊錶的元素位置會調換,這也是jdk1.7hashmap在多執行緒下會產生死迴圈的原因。

hashmap1.8

底層結構:陣列+鍊錶+紅黑樹

擴容操作:

if

(oldtab != null)

// 9.2 如果e的hash值與老表的容量進行與運算為1,則擴容後的索引位置為:老表的索引位置+oldcap

else

}while

((e = next)

!= null)

;// 10.如果lotail不為空(說明老表的資料有分布到新表上「原索引位置」的節點),則將最後乙個節點

// 的next設為空,並將新表上索引位置為「原索引位置」的節點設定為對應的頭節點

if(lotail != null)

// 11.如果hitail不為空(說明老表的資料有分布到新表上「原索引+oldcap位置」的節點),則將最後

// 乙個節點的next設為空,並將新表上索引位置為「原索引+oldcap」的節點設定為對應的頭節點

if(hitail != null)}}

}}// 12.返回新錶

return newtab;

在jdk1.8的擴容中,通過4個鍊錶節點lohead,lotail,hihead,hitail,即高位鍊錶和低位鍊錶的頭尾節點,先遍歷整個鍊錶,通過hash&n,得到的值要麼是0,要麼是16,為0的即為低位煉表裡的節點,為16即為高位煉表裡的節點,最後將尾結點的next置為null,即分成了高位鍊錶和低位鍊錶,低位鍊錶放在新陣列的原來位置,高位鍊錶放在新陣列的原來位置加上原陣列大小,這樣jdk1.8的擴容操作提高了查詢效率,又解決了多執行緒下死迴圈的問題。

HashMap 1 7和1 8的區別

底層資料結構不一樣,1.7是陣列 鍊錶,1.8則是陣列 鍊錶 紅黑樹結構 當鍊表長度大於8,轉為紅黑樹 jdk1.7用的是頭插法,而jdk1.8及之後使用的都是尾插法,那麼他們為什麼要這樣做呢?因為jdk1.7是用單鏈表進行的縱向延伸,當採用頭插法時會容易出現逆序且環形鍊錶死迴圈問題。但是在jdk1...

HashMap 1 7 原始碼講解

1 hashseed 用於鍵的雜湊碼計算上,用於減少雜湊衝突。通過下面所述的inithashseedasneeded方法來進行初始化 2 threshold 表示可以存放的最大量,它的值為loadfactory 陣列容量,但是存在最大值為1 30 1 即2 30 1 3 loadfactory 負載...

HashMap底層(1 7和1 8)的儲存原理

首先說一下jdk1.7版本的存放原理 當例項化後,底層會直接建立乙個長度為16的一維陣列entry table 然後,說一下新增元素時,呼叫put方法 三種情況儲存 方式一 底層根據key計算hash值,計算出索引位置,檢視當前位置是否有值,如果沒有值,直接存放。情況二 當計算出的索引位置,有值時 ...