Java集合—HashMap为什么2倍扩容
原文作者:很閒很快樂
原文地址:HashMap初始容量為什么是2的n次冪及擴容為什么是2倍的形式
?
HashMap的初始容量都是2的n次冪的形式存在的,而擴容也是2倍的原來的容量進行擴容,也就是擴容后的容量也是2的n次冪的形式存在的,下面就來說明一下為什么是2的n次冪的形式!先來看一下源碼,也就是向HashMap中添加元素,或者擴容時是怎么存放元素的。
第一個截圖是向HashMap中添加元素putVal()方法的部分源碼,可以看出,向集合中添加元素時,會使用(n - 1) & hash的計算方法來得出該元素在集合中的位置;而第二個截圖是HashMap擴容時調用resize()方法中的部分源碼,可以看出會新建一個tab,然后遍歷舊的tab,將舊的元素進過e.hash & (newCap - 1)的計算添加進新的tab中,也就是(n - 1) & hash的計算方法,其中n是集合的容量,hash是添加的元素進過hash函數計算出來的hash值。
HashMap的容量為什么是2的n次冪,和這個(n - 1) & hash的計算方法有著千絲萬縷的關系,符號&是按位與的計算,這是位運算,計算機能直接運算,特別高效,按位與&的計算方法是,只有當對應位置的數據都為1時,運算結果也為1,當HashMap的容量是2的n次冪時,(n-1)的2進制也就是1111111***111這樣形式的,這樣與添加元素的hash值進行位運算時,能夠充分的散列,使得添加的元素均勻分布在HashMap的每個位置上,減少hash碰撞,下面舉例進行說明。
當HashMap的容量是16時,它的二進制是10000,(n-1)的二進制是01111,與hash值得計算結果如下:
上面四種情況我們可以看出,不同的hash值,和(n-1)進行位運算后,能夠得出不同的值,使得添加的元素能夠均勻分布在集合中不同的位置上,避免hash碰撞。下面就來看一下HashMap的容量不是2的n次冪的情況,當容量為10時,二進制為01010,(n-1)的二進制是01001,向里面添加同樣的元素,結果為:
可以看出,有三個不同的元素經過&運算得出了同樣的結果,嚴重的hash碰撞了。
終上所述,HashMap計算添加元素的位置時,使用的位運算,這是特別高效的運算;另外,HashMap的初始容量是2的n次冪,擴容也是2倍的形式進行擴容,是因為容量是2的n次冪,可以使得添加的元素均勻分布在HashMap中的數組上,減少hash碰撞,避免形成鏈表的結構,使得查詢效率降低!
總結
以上是生活随笔為你收集整理的Java集合—HashMap为什么2倍扩容的全部內容,希望文章能夠幫你解決所遇到的問題。
                            
                        - 上一篇: JVM—堆栈 堆 方法区 静态区 fin
 - 下一篇: Java集合—List如何一边遍历,一边