最近看了下jdk8的hashmap原始碼,相比於7,在儲存結構上有了些改變。
1.在jdk8之前,hashmap的儲存結構是陣列+鍊錶的形式,那麼這種方式隨著鍊錶的長度增加,效率也凸顯出來。
所以在jdk8中這塊做了優化,當鍊表超過一定長度時轉化為紅黑樹來解決這個問題,下面用流程圖畫出hashmap
的put方法實現邏輯。
下面請帶著這些問題看原始碼,為什麼樹的查詢效率比煉表高,達到什麼樣的條件會擴容,為什麼擴容會影響效率
呢,怎樣實現鍊錶到樹的轉化?
2.先來看下put方法原始碼。
public v put(k key, v value)
final v putval(int hash, k key, v value, boolean onlyifabsent,boolean evict)
v oldvalue = e.value;
if (!onlyifabsent || oldvalue == null)
e.value = value;
afternodeaccess(e);
return oldvalue;}}
++modcount;
//threshold=newthr:(int)(default_load_factor * default_initial_capacity);
//預設0.75*16,大於threshold值就擴容
if (++size > threshold)
resize();
afternodeinsertion(evict);
return null;
1 final
node resize() 12
// 沒超過最大值,就擴充為原來的2倍 13
else
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; 19
else 23
// 計算新的resize上限 24
if(newthr == 0)
30threshold = newthr; 31
@suppresswarnings()
32node newtab = (node)
newnode[newcap]; 33
table = newtab; 34
if(oldtab !=
null)
58// 原索引+oldcap 59
else 66
} while
((e = next) !=
null);
67// 原索引放到bucket裡 68
if(lotail !=
null)
72// 原索引+oldcap放到bucket裡 73
if(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原始碼分析 JDK1 8
陣列 鍊錶 紅黑樹 陣列儲存元素,當有衝突時,就在該陣列位置形成乙個鍊錶,儲存衝突的元素,當鍊表元素個數大於閾值時,鍊錶就轉換為紅黑樹。transient node table transient int size int threshold final float loadfactor 預設初始容...
HashMap原始碼分析 (JDK1 8
首先,hashmap儲存結構類似於位桶,總體結構是 位桶 鍊錶 紅黑樹,這與之前版本的實現有所改進。常量域預設容量16 static final int default initial capacity 1 4 最大容量2的30次方 static final int maximum capacity...