在JDK1.6,JDK1.7中,HashMap采用位桶+鏈表實現,即使用鏈表處理沖突,同一hash值的鏈表都存儲在一個鏈表里。但是當位於一個桶中的元素較多,即hash值相等的元素較多時,通過key值依次查找的效率較低。而JDK1.8中,HashMap采用位桶+鏈表+紅黑樹實現,當鏈表長度超過閾值(8)時,將鏈表轉換為紅黑樹,這樣大大減少了查找時間。在jdk1.8版本后,java對HashMap做了改進,在鏈表長度大於8的時候,將后面的數據存在紅黑樹中,以加快檢索速度。
JDK1.8HashMap的紅黑樹是這樣解決的:
如果某個桶中的記錄過大的話(當前是TREEIFY_THRESHOLD = 8),HashMap會動態的使用一個專門的treemap實現來替換掉它。這樣做的結果會更好
它是如何工作的?前面產生沖突的那些KEY對應的記錄只是簡單的追加到一個鏈表后面,這些記錄只能通過遍歷來進行查找。但是超過這個閾值后HashMap開始將列表升級成一個二叉樹,使用哈希值作為樹的分支變量,如果兩個哈希值不等,但指向同一個桶的話,較大的那個會插入到右子樹里。如果哈希值相等,HashMap希望key值最好是實現了Comparable接口的,這樣它可以按照順序來進行插入。這對HashMap的key來說並不是必須的,不過如果實現了當然最好。如果沒有實現這個接口,在出現嚴重的哈希碰撞的時候,你就並別指望能獲得性能提升了。
為什么是紅黑樹?為什么不直接采用紅黑樹還要用鏈表?
1、因為紅黑樹需要進行左旋,右旋操作, 而單鏈表不需要,
如果元素小於8個,查詢成本高,新增成本低
如果元素大於8個,查詢成本低,新增成本高
