HashMap 容量为2次幂的原因
文章目錄
- 一、什么是HashMap?
- 二、為什么擴容2的n次冪?
一、什么是HashMap?
HashMap是Java中的集合類,是存放鍵值對形式的數據(Key和Value),例如QQ賬號和QQ密碼,QQ賬號就是Key而密碼則是Value
詳細可以看這兩篇上 HashMap源碼剖析(上)——java集合
和下 HashMap源碼剖析(下)——java集合
二、為什么擴容2的n次冪?
首先先看一下HashMap中的putVal方法(存值的)和resize方法(擴容的),之所以HashMap擴容是2的n次冪和這兩個方法有千絲萬縷的聯系。
通過putVal方法可以看出來HashMap在存值時會先把key的hash值和擴容后的長度進行一次按位與運算,其中hash是在hash方法中把key進行計算后的出來的結果,n是擴容的長度(也就是數組的長度,默認為16),然后判斷是否hash碰撞在進行不同的存儲。
通過resize方法可以看出來擴容時會新建一個tab,然后遍歷舊的tab,將舊的元素進行e.hash & (newCap - 1)的計算添加進新的tab中,也就是(n - 1) & hash的計算方法,其中n是集合的容量,hash是添加的元素經過hash函數計算出來的hash值。
之所以這樣2n擴容和上面的兩個方法有極大的關系,首先他們都使用了按位與運算,按位與運算就是把值先變成二進制然后進行運算,如果有0則為0,都為1時則輸出為1,HashMap默認容量為16那么在存放到數組時就是n-1也就是15,而15二進制則是1111擴容后為32-1及11111111
,如果都為1的情況下是可以極大的減少hash碰撞,增加效率的。
通過下面例子來看一下當容量為11111111時按位與運算的結果,通過下面的結果可以看出來結果很分散,大大減少了hash碰撞的發生。
再看一下當容量不為11111111而是為其他值的時候,通過下面的結果可以看出,1、2、4跟不同的值進行hash運算但是結果卻是相同的,也就是發生了hash碰撞。
同時 確定數組位置的實現是 i=(n-1)& hash,其中 n 代表數組的長度,即map的容量。
當n為2的冪次方時,(n-1)& hash 的值是均勻分布的,我們假設n=16,hash從0開始遞增:
當n不為2的冪次方時,(n-1)& hash 的值不是是均勻分布的,我們假設n=15,hash從0開始遞增:
由上面可以看出,當我們根據key的hash確定其在數組的位置時,如果n為2的冪次方,可以保證數據的均勻插入,如果n不是2的冪次方,可能數組的一些位置永遠不會插入數據,浪費數組的空間,加大hash沖突。
另一方面,一般我們可能會想通過 % 求余來確定位置,這樣也可以,只不過性能不如 & 運算。而且當n是2的冪次方時:hash & (length - 1) == hash % length
因此,HashMap 容量為2次冪的原因,就是為了數據的的均勻分布,減少hash沖突,畢竟hash沖突越大,代表數組中一個鏈的長度越大,這樣的話會降低hashmap的性能。
總結
以上是生活随笔為你收集整理的HashMap 容量为2次幂的原因的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 林语堂:《醒觉·对人生的态度》
- 下一篇: 模具师傅告诉我塑胶模具是由这10大系统构