摘抄部分如下:
當我們put的時候,首先計算key
的hash
值,這裡呼叫了hash
方法,hash
方法實際是讓key.hashcode()
與key.hashcode()>>>16
進行異或操作,高16bit補0,乙個數和0異或不變,所以 hash 函式大概的作用就是:高16bit不變,低16bit和高16bit做了乙個異或,目的是減少碰撞。按照函式注釋,因為bucket陣列大小是2的冪,計算下標index = (table.length - 1) & hash
,如果不做 hash 處理,相當於雜湊生效的只有幾個低 bit 位,為了減少雜湊的碰撞,設計者綜合考慮了速度、作用、質量之後,使用高16bit和低16bit異或來簡單處理減少碰撞,而且jdk8中用了複雜度 o(logn)的樹結構來提公升碰撞下的效能。
putval方法執行流程圖
//實現map.put和相關方法
final v putval(int hash, k key, v value, boolean
onlyifabsent,
boolean
evict)
//判斷鍊錶中結點的key值與插入的元素的key值是否相等
if (e.hash == hash &&((k = e.key) == key || (key != null &&key.equals(k))))
//相等,跳出迴圈
break
;
//用於遍歷桶中的鍊錶,與前面的e = p.next組合,可以遍歷鍊錶
p =e;}}
//判斷當前的key已經存在的情況下,再來乙個相同的hash值、key值時,返回新來的value這個值
if (e != null
) }
//結構性修改
++modcount;
//步驟⑥:超過最大容量就擴容
//實際大小大於閾值則擴容
if (++size >threshold)
resize();
//插入後**
afternodeinsertion(evict);
return
null
;}①.判斷鍵值對陣列table[i]是否為空或為null,否則執行resize()進行擴容;
②.根據鍵值key計算hash值得到插入的陣列索引i,如果table[i]==null,直接新建節點新增,轉向⑥,如果table[i]不為空,轉向③;
③.判斷table[i]的首個元素是否和key一樣,如果相同直接覆蓋value,否則轉向④,這裡的相同指的是hashcode以及equals;
④.判斷table[i] 是否為treenode,即table[i] 是否是紅黑樹,如果是紅黑樹,則直接在樹中插入鍵值對,否則轉向⑤;
⑤.遍歷table[i],判斷鍊錶長度是否大於8,大於8的話把鍊錶轉換為紅黑樹,在紅黑樹中執行插入操作,否則進行鍊錶的插入操作;遍歷過程中若發現key已經存在直接覆蓋value即可;
⑥.插入成功後,判斷實際存在的鍵值對數量size是否超多了最大容量threshold,如果超過,進行擴容。
HashMap的Put方法(二)
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 ext...
hashmap 的put與get 筆記
put操作 成員變數 transient entry table entry empty table 陣列 1 資料介面就是陣列 加鍊表 hashmap有 table陣列專門記錄 的就是,正常的put值就是計算出key的hashcode然後找出索引 i 去table陣列中找,如果存在就用單鏈表儲存,...
HashMap原始碼解析《一》put方法
在jdk1.8裡邊 hashmap的實現原理不僅僅只由位桶 鍊錶實現 增加位桶 紅黑樹實現,在桶中鍊錶儲存的元素個數到達閾值時 預設為8 將在底層將鍊錶轉為紅黑樹,但因為我本人紅黑樹掌握的並不好,所以不討論有關紅黑樹,本文主要講解基礎,hashmap的put方法,其他請等待下文 一,所涉及到的名詞 ...