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