hashmap原始碼面試分析

rudynan發表於2020-11-04

HashMap原始碼問題解析

  1. 問: 說一說對hash的理解
    答: hash是對任意長度的輸入輸出為相同長度的輸出
  2. 問: hash演算法的問題
    答: hash衝突問題
  3. 問: hash衝突是否可以避免
    答: 不可以避免,只能儘量規避
  4. 問: 優秀的hash演算法有什麼特性
    答: 1. 任何微小的變化hash的結果都不相同
    2. hash不可逆
    3. 長字串的hash效率要高
    4. hash值儘量雜湊平均
    5. 相同的值hash值相同
  5. 問: hashmap的資料結構
    答: 以1.8為例 陣列+連結串列+紅黑樹 資料儲存在node物件中,node中有key value next hash等欄位
  6. 問: 雜湊表的初始長度是多長
    答: 預設是16
  7. 問: 雜湊表是什麼時候建立
    答: 第一次put的時候建立(懶載入)
  8. 問: 預設的負載因子是多少,負載因子的作用
    答: 空參構造建立的hashmap的負載因子是0.75,作用是當node數量大於陣列長度的0.75的時候進行resize擴容
  9. 問: 連結串列轉化紅黑樹需要什麼條件
    答: 需要兩個條件 連結串列長度大於等於7並且陣列的長度大於等於64才進行樹化
  10. 問node物件的hash值是怎麼得來的,為什麼這麼操作
    答: 是根據key的hashcode值在與key的hashcode的高16位異或操作得來的,是為了在陣列中分佈的更加隨機均勻,因為hashmap的資料計算陣列下標的方法是(tab.length-1)&hash,tab.length大部分情況下小於2^16也就是25536(規則表明tab.length必須是2的次方數) 所以大部分情況下是hash的低16位參與運算,為了讓hash更加隨機均勻,多一次與key的hashcode異或運算來加強hash值的隨機分佈,讓hashcode沒一位都參與到運算中
  11. 問: hashmap put方法的詳細流程
    答: key經過定址查到在陣列中的下標
    1. 如果陣列下標為null直接存入node
    2. 如果不為空比較值 相同覆蓋 如果是樹則按紅黑樹規則放入 如果不是樹 進行尾插連結串列長度大於等於7並且陣列長度大於64轉樹 長度超過閾值resize
  12. 問: 紅黑樹的原則
    答: 1. 葉子節點到根節點的路徑黑色節點數量一致(黑高)
    2. 葉子節點都是黑色的
    3. 不能有兩個紅色的節點相連
    4. 根節點一定是黑色的
    5. 插入的節點一定是紅色的(紅插)
  13. 問: jdk1.8hashmap為什麼引入紅黑樹
    答: 因為連結串列太長的話會導致查詢效率降低hash的目的是儘量實現o(1)的,連結定址很慢
  14. 問: hashmap什麼時候會觸發擴容
    答: put操作的時候,有個欄位記錄資料量當大於擴容閾值的時候擴容
  15. 問: hashmap怎麼擴容
    答: 陣列長度一定是2的次方數,每次擴容是原先長度左移一位<<1
  16. 問: 老陣列的資料怎麼遷移到新陣列中
    答: 1. hash未衝突的直接根據新的陣列長度計算放入即可
    2. 如果已經成紅黑樹
    3. 已經是連結串列未成樹會hash&舊陣列長度(oldcap) 等於0的放低鏈 不等於的放高鏈 低鏈的放原來的index 高鏈放原來的index+oldlength的位置
    解釋:在hashmap定址演算法計算得出(hash&(length-1)) 一條連結串列的資料肯定會分成兩個連結串列 位置一個是原index 另一個是原index+oldlength
    原先的length長度為16 二進位制為10000 那麼length就是16-1 =15(1111)就是hash&1111 以第15個桶為例,那麼hash的值就可能是01111或者11111
    擴容後length變為32 二進位制為100000 hash&11111 那麼如果15這個桶位置原先hash是01111的node就放在他原先的15的這個位置,hash為11111的就放在
    32這個桶的位置
    01111 & 10000 = 0 這個放15這個位置
    11111 & 10000 != 0 放32 15+16 = 31這個位置

相關文章