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...