HashMap主要是用來處理鍵值對資料。随着JDK版本的更新,JDK1.8對HashMap對底層也做了一些優化。今天我帶大家一起來結合源碼,深入淺出HashMap工作原理。 l
HashMap是基于哈希表對Map接口的實作類,它的特點是通路資料的速度快,并不是按順序來周遊。 HashMap提供所有可選的映射操作,但不能保證映射順序不變,并且允許使用空值和空鍵。HashMap也并不是線程安全的,當存在多個線程同時寫入時,可能會導緻資料不一緻的情況。
1、HashMap中的關鍵屬性
【導覽列:關鍵屬性】
要透徹了解HashMap原理,首先需要對以下幾個關鍵屬性有一個基本的認識。

我們看到,HashMap的源碼片段:
第一個屬性 loadFactor,它是負載因子,預設值是0.75,表示擴容前 。
第二個屬性 threshold 它是記錄HashMap所能容納的鍵值對的臨界值,它的計算規則是負載因子 乘以 數組長度。
第三個屬性 size,它用來記錄HashMap實際存在的鍵值對的數量。
第四個屬性 modCount,它用來記錄HashMap内部結構發生變化的次數。
第五個是常量屬性DEFAULT_INITIAL_CAPACITY ,它規定 的預設容量是16。
2、HashMap的存儲結構
【導覽列:存儲結構】
HashMap采用的是 的存儲結構。HashMap的數組部分稱為Hash桶,數組元素儲存在一個叫做table的屬性中。當連結清單長度大于等于8時,連結清單資料将會以紅黑樹的形式進行存儲,當長度降到6時,又會轉成連結清單形式存儲。
每個Node節點,儲存了用來定位數組索引位置的hash值、Key、Value和連結清單指向的下一個Node節點。而Node類是HashMap的内部類,它實作了Map.Entry接口,它的本質其實可以簡單的了解成就是一個鍵值對。來看一下源碼。
3、HashMap的工作原理
【導覽列:工作原理】
當我們向HashMap中插入資料時,首先要确定Node在數組中的位置。那如何确定Node的存儲位置呢?以添加Key為字元串“e”的對象為例:
HashMap首先調用hashCode()方法,擷取Key的hashCode值為h。然後對h值進行高位運算;将h右移16位取得h的高16位,與 進行異或運算,最後得到h的值與 ( table.length - 1 )進行與運算獲得該對象的保留位,最後計算出下标。當然,這是最官方的描述。有的小夥伴可能已經迷糊了。其實,這段運算過程,簡單地了解成求模取餘法。
就是用hash值和數組的長度減1,取模,最後得到數組的下标,這樣可以保證數組下标不越界。隻不過,位運算是二進制運算,效率更高。
最後,來看一段動畫示範,假設有“a”、“b”、“d”、“r”,“t”,“e”的Key。通過計算得到的下标分别為 1 、2 、 4 、2 、4 、5
它們的插入順序如動畫所示。
如果我們再次插入 "a",“g”,“i”,null 四個Key,來看HashMap的内部變化。
當插入第二個以a為Key的對象時,會将新值指派給a的值。當插入的對象大小超過臨界值時,HashMap将建立一個桶數組并重新指派(當然,JDK1.7和1.8重新指派的方式略有不同)
這個時候,HashMap鍵的輸出順序為 null、a、b、r、d、t、e、g、i
HashMap的工作原理,你搞懂了嗎?
S信【Tom】或【666】即可免費領取需要更多幹貨内容,還有海量面試資料,隻彈幹貨不慘水!