hashmap原始碼解析(負載因子,樹化策略,內部hash實現,resize策略)
內部屬性:
負載因子: finalfloat
loadfactor(預設為0.75f)
實際容量:
int threshold = loadfactor *tab.length;
樹化閾值:
int treeify_threshold = 8;
解除樹化閾值:
int untreeify_threshold = 6;
hashmap也採用懶載入策略,第一次put時初始化雜湊表。
樹化邏輯:索引下標對應的鍊錶長度達到閾值8並且當前雜湊表長度達到64才會樹化,否則只是呼叫resize方法進行雜湊表擴容。
resize():擴容為原先陣列的2倍
負載因子過大會導致雜湊衝突明顯增加,節省記憶體.負載因子過小會導致雜湊表頻繁擴容,記憶體利用率低。
為何jdk1.8要引入紅黑樹?當鍊表長度過長時,會將雜湊表查詢的時間複雜度退化為o(n)
樹化保證即便在雜湊衝突嚴重時,查詢時間複雜度也為o(logn)
當紅黑樹節點個數在擴容或刪除元素時減少為6以下,在下次resize過程中會將紅黑樹退化為鍊錶,節省空間。
public v put(k key, v value)
hashmap內部hash
static final int hash(object key)
為何不直接使用object提供的hashcode?
將雜湊碼保留一半,將高低位都參與雜湊運算,減少記憶體開銷,減少雜湊衝突。
(h = key.hashcode()) ^ (h >>> 16)
put內部邏輯:
1.雜湊表索引下標計算:
i = (n - 1) & hash
保證求出的索引下標都在雜湊表的長度範圍之內。
2.n : 雜湊表長度
n必須為2^n,保證雜湊表中的所有索引下標都會被訪問到。
若n=15,則以下位置永不可能儲存元素
0011
0101
1001
1011
1101
1111
15:0000 1111
final v putval(int hash, k key, v value, boolean onlyifabsent,
boolean evict)
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k))))
break;
p = e;}}
v oldvalue = e.value;
if (!onlyifabsent || oldvalue == null)
e.value = value;
afternodeaccess(e);
return oldvalue;}}
++modcount;
// 此時新增了新節點
if (++size > threshold)
// 擴容
resize();
afternodeinsertion(evict);
return null;
}
HashMap原理 原始碼解析
一 前言 hashmap是map實現中最常使用的,具有快速訪問的優點,所以很有必要深入到原始碼去了解其實現原理。方法 的原始碼分析。二 hashmap的資料結構 hashmap 可以理解為由陣列和鍊錶組成的儲存結構,如圖 軸方向上是乙個陣列,y方向是鍊錶。乙個節點的資訊包括 hash key val...
HashMap底層實現原理 原始碼
基於雜湊表的 map 介面的實現。此實現提供所有可選的對映操作,並允許使用null值 和 null鍵 檢視構造方法 預設初始的容量為16 arraylist預設初始值是 10 預設載入因子為0.75,什麼意思呢?就是說當資料元素達到容量的75 時,就會進行擴容 方法和map中的方法是一樣的 預設初始...
HashMap實現原理,原始碼分析
一 原始碼分析 定義陣列的初始容量。static final int default initial capacity 1 4 aka 16 定義陣列最大容量 static final int maximum capacity 1 30 定義負載因子預設值 static final float de...