JDK 1 8 HashMap擴容原理

2021-10-07 15:42:02 字數 2199 閱讀 9378

擴容前計算索引

1010 0101

&0000 1111

0000 0101

索引結果

5擴容以後容量是n=32(對應的二進位制是0001 1111),node本身的hash值是不變的,仍然是1010 0101,那麼擴容後node 的索引的計算是通過如下方式得到

擴容後計算索引

1010 0101

&0001 1111

0000 0101

索引結果

5發現計算後的索引結果和擴容前是一樣的,那麼是什麼原因導致擴容前後的索引是一樣的?或者是不一樣的呢?我們把擴容前後的兩次hash計算索引的過程放在一起對比一下

擴容前計算索引

擴容後計算索引

(hash)

10100101

10100101

(n-1)&

00001111

&00011111

00000101

00000101

索引結果55

先給出結論,注意看一下(n-1) 的值他轉化為二進位制以後的第五位,也就是表中加粗的數字

擴容前計算索引

擴容後計算索引

(hash)

10110101

10110101

&(n-1)

00001111

&00011111

00010101

00010101

索引結果

516+ 5

我們發現,最後擴容以後計算結果中第5位變成了1,低四位不變,也就是16 + 5,而這增加的16恰好是map擴容前的容量16,回到上面的問題,node的hash值的二進位制如果第5位是1,擴容後的索引就是 擴容前的容量 + 原索引值。

hash值二進位制第五位是1

hash值二進位制第五位是0

10110101

10100101

&00010000

&00010000

00010000

00000000

第五位結果10

final node

resize()

elseif(

(newcap = oldcap <<1)

< maximum_capacity &&

oldcap >= default_initial_capacity)

//table的容量乘以2,threshold的值也乘以2

newthr = oldthr <<1;

// double threshold

}else

if(oldthr >0)

// initial capacity was placed in threshold

//使用帶有初始容量的構造器時,table容量為初始化得到的threshold

newcap = oldthr;

else

if(newthr ==0)

threshold = newthr;

@suppresswarnings()

node

newtab =

(node

)new

node

[newcap]

; table = newtab;

if(oldtab != null)

else

}while

((e = next)

!= null);if

(lotail != null)

if(hitail != null)}}

}}return newtab;

}

參考

擴容機制核心方法node%3ck%2cv%3e%5b%5d%20resize()

今天了聊聊jdk1 8 HashMap的擴容原理

其實hashmap已經是乙個老生常談的問題了在面試中也是深受面試官喜愛,在網上如果搜尋hashmap原理,原始碼分析得文章也是非常多本文基於jdk1.8分析下擴容原理 jdk1.7與jdk1.8最大的差別是解決hash衝突的資料結構由原來的鍊錶變為鍊錶 紅黑樹 首先翻一下該方法注釋,翻譯出來感覺還是...

JDK1 8 HashMap原始碼解析

普通常量 儲存node鍊錶的陣列 transient node table 由node節點構成的set集合 transient set entryset hashmap儲存元素的數量 transient int size 記錄hashmap結構性變化的次數 value覆蓋不算 和fail fast機...

JDK 1 8 HashMap原始碼解析

put方法分析 public v put k key,v value hash方法解析 減少hash衝突 static final int hash object key putval方法具體實現 final v putval int hash,k key,v value,boolean onlyi...