陣列+鍊錶/紅黑樹:陣列儲存元素,當有衝突時,就在該陣列位置形成乙個鍊錶,儲存衝突的元素,當鍊表元素個數大於閾值時,鍊錶就轉換為紅黑樹。
transient node table;
transient
int size;
int threshold;
final
float loadfactor;
// 預設初始容量16
static
final
int default_initial_capacity = 1
<< 4;
// 最大容量2^30
static
final
int maximum_capacity = 1
<< 30;
// 預設負載因子
static
final
float default_load_factor = 0.75f;
// 鍊錶轉紅黑樹的閾值
static
final
int treeify_threshold = 8;
node table的初始化長度length(預設值是16),loadfactor為負載因子(預設值是0.75),threshold是hashmap所能容納的最大資料量的node(鍵值對)個數。threshold = length * loadfactor。也就是說,在陣列定義好長度之後,負載因子越大,所能容納的鍵值對個數越多。
在jdk1.8的實現中,優化了高位運算的演算法,通過hashcode()的高16位異或低16位:
(h =k.hashcode()) ^ (h >>> 16)
從速度、功效、質量來考慮,這麼做可以在陣列table的length比較小的時候,也能保證考慮到高低bit都參與到hash的計算中,同時不會有太大的開銷。
/**
* 計算雜湊值
*/static
final
int hash(object key)
/**
* 計算索引
*/static
int indexfor(int h, int length)
else
具體**如下:
do
else
} while ((e = next) != null);
if (lotail != null)
if (hitail != null)
例:key1=5,key2=21
擴容前:
hash(key1) = 5 mod 16 = 5
hash(key2) = 21 mod 16 = 5
擴容後:
hash(key1) = 5 mod 32 = 5
hash(key2) = 21 mod 32 = 21 = 5 + 16
利用位運算,提高效率:
原容量oldcap= 16,即0001 0000,oldcap-1 = 0000 1111
新容量newcap = 32,即0010 0000,newcap-1 = 0001 1111
判斷對應位是否為1:key & cap
獲取索引:key & (cap - 1)
rehash之後,n為原來的2倍,所以n-1的mask範圍在高位多1bit(紅色),因此新的index就會發生這樣的變化:
// 判斷是否擴容
if (++size > threshold)
resize();
afternodeinsertion(evict);
return
null;
}(2)resize
final node resize()
12// 沒超過最大值,就擴充為原來的2倍
13else
if ((newcap = oldcap << 1) < maximum_capacity &&
14 oldcap >= default_initial_capacity)
15 newthr = oldthr << 1; // double threshold
16 }
17else
if (oldthr > 0) // initial capacity was placed in threshold
18 newcap = oldthr;
19else
23// 計算新的resize上限
24if (newthr == 0)
30 threshold = newthr;
31@suppresswarnings()
32 node newtab = (node)new node[newcap];
33 table = newtab;
34if (oldtab != null)
5859
else
66 } while ((e = next) != null);
67// 原索引放到bucket裡
68if (lotail != null)
72// 原索引+oldcap放到bucket裡
73if (hitail != null)
77 }
78 }
79 }
80 }
81return newtab;
82 }
分析HashMap 的 JDK 原始碼
緣由 今天好友拿著下面的 問我為什麼 map.entry 這個介面沒有實現 getkey 和 getvalue 方法,卻可以使用,由此,開啟了一番查閱 jdk 原始碼的旅途 map map new hashmap map.put 1,張三 map.put 2,李四 map.put 3,王五 map....
hashmap原始碼分析jdk8
最近看了下jdk8的hashmap原始碼,相比於7,在儲存結構上有了些改變。1.在jdk8之前,hashmap的儲存結構是陣列 鍊錶的形式,那麼這種方式隨著鍊錶的長度增加,效率也凸顯出來。所以在jdk8中這塊做了優化,當鍊表超過一定長度時轉化為紅黑樹來解決這個問題,下面用流程圖畫出hashmap 的...
HashMap原始碼分析 (JDK1 8
首先,hashmap儲存結構類似於位桶,總體結構是 位桶 鍊錶 紅黑樹,這與之前版本的實現有所改進。常量域預設容量16 static final int default initial capacity 1 4 最大容量2的30次方 static final int maximum capacity...