擴容前計算索引
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...