hashmap類中有如下put方法(方法體省略):
public呼叫關係:v put(k key, v value) {}
final v putval(int hash, k key, v value, boolean
onlyifabsent,
boolean
evict) {}
public
void putall(map extends k, ? extends v>m) {}
public v putifabsent(k key, v value){}
根據方法呼叫關係圖可以看到putval方法是hashmap put操作最關鍵的方法,在詳細分析putval原始碼之前,我們先看一下put方法流程圖:
流程講解:
1)計算key的hash值,hash值的計算方法為key的hash值高16位不變,低16位與高16位進行異或操作,作為keyhash值。至於為什麼這麼做,這裡不做重點講解。
2)如果陣列table是否為null或長度是否等於0,條件為true時進行資料table擴容(實際執行resize方法),擴容操作以後單獨講解。
3)根據hash值計算value將要存放的位置,即計算陣列table索引。索引變數i = (n - 1) & hash;陣列table的長度都是2的冪,因此這裡直接對陣列長度和hash值進行與運算,也就是說hash值的高位都被與運算置為0了,i僅與hash值的低n位有關。
4)判斷table[i]是否是null,如果是null直接進行value插入。
5)如果table[i]不是null,接著判斷key是否重複,如果重複直接進行覆蓋插入。
6)如果key不重複,判斷table[i]是否是treenode型別,如果是紅黑樹,直接插入。
7)如果不是treenode就遍歷鍊錶,遍歷時預判斷插入新的value後,鍊錶長度是否大於等於8。條件為true時執行鍊錶轉紅黑樹,然後插入value。
8)如果上面鍊錶長度小於8執行鍊錶插入。
9)最後檢查陣列是否需要擴容。
注:流程圖中黃色標註的1,2,3,4我們以後再逐個分析。
putval原始碼:
final v putval(int hash, k key, v value, booleanonlyifabsent,
boolean
evict)
if (e.hash == hash &&((k = e.key) == key || (key != null &&key.equals(k))))
break
; p =e;}}
if (e != null)
}++modcount;
//陣列table擴容,陣列的長度一直都是2的冪次方
if (++size >threshold)
resize();
afternodeinsertion(evict);
return
null
; }
HashMap的put方法的具體流程
摘抄部分如下 當我們put的時候,首先計算key的hash值,這裡呼叫了hash方法,hash方法實際是讓key.hashcode 與key.hashcode 16進行異或操作,高16bit補0,乙個數和0異或不變,所以 hash 函式大概的作用就是 高16bit不變,低16bit和高16bit做了...
HashMap原始碼解析《一》put方法
在jdk1.8裡邊 hashmap的實現原理不僅僅只由位桶 鍊錶實現 增加位桶 紅黑樹實現,在桶中鍊錶儲存的元素個數到達閾值時 預設為8 將在底層將鍊錶轉為紅黑樹,但因為我本人紅黑樹掌握的並不好,所以不討論有關紅黑樹,本文主要講解基礎,hashmap的put方法,其他請等待下文 一,所涉及到的名詞 ...
HashMap原始碼之get與put方法
hashmap是基於陣列和鍊錶來儲存鍵值對物件的,我們簡單看下get和put方法的原始碼。1 我們呼叫put方法來儲存鍵值對時,它先呼叫hash方法來計算hashcode,然後用hashcode和entry陣列的大小來做按位與操作,求出所在的entry陣列的下標位置。通過key與下標所在的entry...