HashMap實現記憶體擴容

2021-09-25 21:33:42 字數 1507 閱讀 2358

hashmap實現的方式有多種,主要區別個人認為就是在hash查詢,如何解決hash碰撞上。(hash函式用什麼,怎麼雜湊,這個跟著大家呼叫庫就好了,反正我也證明不了hash函式裡面的數學問題)

在這裡說的是 陣列和鍊錶混用的一種,如下圖(以下都來自參考文章)。

該為jdk7的 hashmap設計模型,橫向為陣列結構,縱向為鍊錶結構。

然後很容易理解,當乙個key雜湊之後,沒有產生碰撞,直接放進陣列的格仔裡,當key雜湊之後產生了碰撞,即縱向擴充套件,用鍊錶的串聯起來。

這裡有乙個小問題?

不同的key1, key2產生相同雜湊值hash_value,串聯之後,取值時,輸入的key也會雜湊之後得到相同的hash_value去定位,此時如何區分該取key1還是該取key2呢?

此時只需要把key1,key2本身也存在鍊錶的節點裡,通過hash_value定位到煉表頭結點,然後遍歷鍊錶,對比key和key1,key2,相同的那個就是要取出的值。

那怎麼通過hash_value定位呢?

既然是陣列,那就遍歷陣列,用陣列元素的值和hash_value對比即可。此時的時間複雜度為o(n).如果陣列的長度很長,o(n)就會很大,可以將陣列轉為紅黑樹來避免o(n)。

golang的slice有len,cap兩個引數,cap為容量,當當前長度大於cap時,cap會乘2,有個測試的小例子。

同理hashmap也是作了類似的處理,

hashmap關鍵引數

size

hashmap中的kv組合的總數量,拿上圖舉例,size = 4(陣列元素)+4(鍊錶節點) = 9。

capacity

容量,hashmap中陣列的長度,也稱作桶的數量,預設值是default_initial_capacity=16。拿上圖舉例,capacity=10。

loadfactor

裝載因子,預設是0.75,此數值可以衡量hashmap滿的程度。

threshold

擴容閥指,threshold = capacity * loadfactor ,當hashmap的size大於或者等於 threshold 時,hashmap將進行擴容。

maximum_capacity

hashmap的最大容量,1 << 30 = 230

但hashmap在設計上會把陣列的長度設計為2的n次冪,實現方式為只要初始化陣列長度時長度為2的n次冪,之後每次陣列擴容時乘2,那陣列就一直為2的n次冪,這樣的設計的目的是減少雜湊碰撞,使得要儲存的元素能均勻的分布在陣列中,如何避免的,在數學上,在下暫時還不能理解。

如何在初始化陣列長度時長度為2的n次冪

有一段**一定要備註一下,個人覺得很巧妙。

private

static

introunduptopowerof2

(int number)

HashMap底層實現原理 擴容機制

hashmap基於map介面實現,元素以鍵值對的方式儲存,並且允許使用null 建和null 值,因為key不允許重複,因此只能有乙個鍵為null,另外hashmap不能保證放入元素的順序,它是無序的,和放入的順序並不能相同。hashmap的容量,預設是16 the default initial ...

hashMap擴容機制

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

HashMap擴容機制

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