HashMap源碼學習及7/8的對比

HashMap1.7

Jdk1.7的HashMap實質上是一個Entry數組,數組的每一個元素是一個單向鏈表,其數據結構以下:數組

HashMap的put方法:安全

  1. 判斷map中的數組是不是空的,是則初始化數組。(可見HashMap在構造函數的時候其實啥都沒幹,真正初始化數組的時候是在put方法執行的)
  2. 判斷key值是否爲null,爲null則將值放入在數組的第一個元素即table[0]
  3. 根據key計算出hash值
  4. 經過hash值從table數組找到對應的下表
  5. 取數組table對應下標的鏈表並遍歷判斷是否存在相同key值,存在則覆蓋舊值並返回
  6. key值不存在則將Entry添加到鏈表中

仔細看看addEntry方法的實現,主要流程以下:數據結構

  1. 首先判斷當前size是否已經達到了閾值且對應數組小標已經有值則須要擴容,擴容必定是數組大小的2倍,擴容後從新計算元素在新數組裏的下表
  2. 在數組對應下表添加新的原色(新添加元素必定是添加都鏈表的表頭,將next指向舊值)

HashMap的get方法函數

  1. 判斷key值是否爲空,爲空直接從數據的第一個元素返回值
  2. 根據key計算出hash,根據hash找到對應數組下表,而後在根據hash從對應鏈表中取值便可

HashMap存在的非線程安全的問題:線程

  1. 擴容時候造成環形鏈表
  2. 添加數據時數據丟失

HashMap1.8

HashMap1.8相比1.7有比較大的改進,數據結構由1.7的數組+鏈表修改成數組+鏈表+紅黑樹,其中當鏈表的元素大於等於8的時候會轉換成紅黑樹存儲,另外就是擴容的時間點,1.7是先擴容再添加元素,1.8是先添加元素後再擴容。其數據結構由1.7的Entry數組變爲Node數組,如: blog

put方法主要代碼以下: get

get方法,相對比較簡單:hash

  1. 經過key計算出hash值,而後找到對應數組的下表 2.判斷對應下表的第一個值是否就是要找的對應key值,如果,直接返回,不然進行第3步
  2. 判斷元素是鏈表仍是紅黑樹,而後相應的獲取對應的值。

總結:table

  1. 兩個版本採用的存儲結構不一樣,一個是數組+鏈表,一個是數組+鏈表+紅黑樹
  2. 擴容順序不一樣,1.7是先擴容再插入,1.8是先插入在擴容
  3. 1.8中鏈表轉紅黑樹的條件是鏈表長度大於等於8 4.均不是線程安全
  4. 待補充
相關文章
相關標籤/搜索