HashMap的擴容機制 resize

2022-07-25 03:24:10 字數 2171 閱讀 1230

hashmap底層邏輯

當我們往hashmap中put元素的時候,先根據key的hash值得到這個元素在陣列中的位置(即下標),然後就可以把這個元素放到對應的位置中了。如果這個元素所在的位子上已經存放有其他元素了,

那麼在同乙個位子上的元素將以鍊錶的形式存放,新加入的放在鏈頭,最先加入的放在鏈尾。從hashmap中get元素時,首先計算key的hashcode,找到陣列中對應位置的某一元素,然後通過key的equals

方法在對應位置的鍊錶中找到需要的元素。

帶著問題去思考?1.獲取陣列指標演算法是什麼?

(length - 1) &hash

​通過key獲取hash值,然後『&』陣列長度減一的值

2.為什麼hashmap陣列長度預設為16?

這個問題其實可以分成2個問題: 1.預設長度為什麼2的n次冪方 2.為什麼選擇16作為預設長度
預設長度為什麼2的n次冪方?

為什麼hashmap的陣列初始化大小都是2的次方大小時,hashmap的效率最高?我以2的4次方舉例,來解釋一下為什麼陣列大小為2的冪時hashmap訪問的效能最高。

解釋說明:

看上圖,左邊兩組是陣列長度為16(2的4次方),右邊兩組是陣列長度為15。兩組的hashcode均為8和9,但是很明顯,當它們和1110「與」的時候,產生了相同的結果,也就是說它們會定位到陣列中的同乙個位置上去,

這就產生了碰撞,8和9會被放到同乙個鍊錶上,那麼查詢的時候就需要遍歷這個鍊錶,得到8或者9,這樣就降低了查詢的效率。同時,我們也可以發現,當陣列長度為15的時候,hashcode的值會與14(1110)進行「與」,

那麼最後一位永遠是0,而0001,0011,0101,1001,1011,0111,1101這幾個位置永遠都不能存放元素了,空間浪費相當大,更糟的是這種情況中,陣列可以使用的位置比陣列長度小了很多,這意味著進一步增加了碰撞的機率,減慢了查詢的效率!

結論:

所以說,當陣列長度為2的n次冪的時候,不同的key算得得index相同的機率較小,那麼資料在陣列上分布就比較均勻,也就是說碰撞的機率小,相對的,查詢的時候就不用遍歷某個位置上的鍊錶,這樣查詢效率也就較高了。
那為什麼選擇16作為預設值呢?

在小資料量的情況下16比15和20更能減少key之間的碰撞,而加快查詢效率。所以在儲存大容量資料的時候,最好預先指定hashmap為2的整數次冪次方,就算不指定的話也會以大於且最接近指定值大小的2次冪來初始化的
3、hashmap的resize

當hashmap中的元素越來越多的時候,碰撞的機率也就越來越高(因為陣列的長度是固定的),所以為了提高查詢的效率,就要對hashmap的陣列進行擴容,陣列擴容這個操作也會出現在arraylist中,所以這是乙個通用的操作,

很多人對它的效能表示過懷疑,不過想想我們的「均攤」原理,就釋然了,而在hashmap陣列擴容之後,最消耗效能的點就出現了:原陣列中的資料必須重新計算其在新陣列中的位置,並放進去,這就是resize。那麼hashmap什麼時候

進行擴容呢?當hashmap中的元素個數超過陣列大小*loadfactor時,就會進行陣列擴容,loadfactor的預設值為0.75,也就是說,預設情況下,陣列大小為16,那麼當hashmap中元素個數超過16*0.75=12的時候,就把陣列的大

小擴充套件為2*16=32,即擴大一倍,然後重新計算每個元素在陣列中的位置,而這是乙個非常消耗效能的操作,所以如果我們已經預知hashmap中元素的個數,那麼預設元素的個數能夠有效的提高hashmap的效能。比如說,我們有1000個

元素new hashmap(1000), 但是理論上來講new hashmap(1024)更合適,不過上面annegu已經說過,即使是1000,hashmap也自動會將其設定為1024。 但是new hashmap(1024)還不是更合適的,因為0.75*1000 < 1000,

也就是說為了讓0.75 * size > 1000, 我們必須這樣new hashmap(2048)才最合適,既考慮了&的問題,也避免了resize的問題。

hashMap擴容機制

擴容時空間大小變化 hashmap中,雜湊桶陣列table的長度length大小必須為2的n次方 一定是合數 這是一種非常規的設計,常規的設計是把桶的大小設計為素數。相對來說素數導致衝突的概率要小於合數,具體證明可以參考 hashtable初始化桶大小為11,就是桶大小設計為素數的應用 hashta...

HashMap擴容機制

當map元素容量超過設定的閾值threshold capacity loadfactor時進行擴容,如下圖所示 原理 建立更大容量的新陣列,重新計算每個元素在新陣列中的位置進行遷移。缺點 每個元素需要重新計算hash 鍊錶中元素順序每次遷移後被倒置 原理 在擴充hashmap的時候,不需要像jdk1...

總結 HashMap的擴容機制

jdk1.7 hashmap擴容原理 原理 建立乙個容量的新陣列,重新計算每個元素在陣列中的位置並且進行遷移。缺點 1 擴容後每個元素需要重新計算hash。2 鍊錶中元素順序 每次遷移後被倒置。jdk1.8 hashmap擴容策略 想法 hashmap是先插入然後再擴容,有的時候我們可能會想如果先增...