面試集錦(十二)hashMap

zhusir發表於2018-08-22

hashmap

底層是基於陣列+連結串列實現的,真正存放資料的是entry<k,v>的陣列

hashmap如何解決碰撞問題

當不同的物件發生碰撞時,HashMap通過單連結串列來解決,將新元素加入<連結串列>表頭(頭插法),通過next指向原有的元素。單連結串列在Java中的實現就是物件的引用(複合)。

put方法

  1. 判斷當前陣列是否需要初始化
  2. 如果key為空,則put一個空值進去
  3. 根據key算出hashcode
  4. 根據hashcode定位所在的桶(連結串列)
  5. 如果桶是連結串列要遍歷裡面的hashcode和key和傳入的key是否相等,相等則覆蓋,並返回原來的值
  6. 如果桶是空的,說明當前位置沒有資料,則新增一個entry物件寫入當前位置

get方法

  1. 根據key來算出hashcode,然後定位到具體的桶中
  2. 判斷該位置是否是連結串列
  3. 不是連結串列就根據key,key的hashcode是否相等來返回值
  4. 如果是連結串列則需要遍歷知道key及hashcode相等時候返回值
  5. 啥都沒有就返回null

jdk1.8做的優化

對大連結串列進行了優化,超過閾值後將連結串列修改為紅黑樹後查詢效率大大增加(當連結串列較長時轉為將連結串列紅黑樹),未優化之前是o(n),優化後是o(log n)

會出現的問題

jdk沒有對它進行任何的同步操作,所以會出現併發訪問的問題,甚至會出現死迴圈導致系統不可用

解決辦法

concurrenHashMap(guava中的cache採用的就是這個)

concurrentHashMap

原理:concurrenthashmap採用了分段鎖技術,其中segment繼承於reentrantlock。每當一個執行緒佔用鎖訪問一個segment時,不會影響到其他的segment

jdk1.7和1.8的不同

1.7採用了分段鎖,1.8取消了分段鎖,改用CAS + synchronized來保證併發安全性

1.8之後在資料結構上做了改動,超過閾值後採用紅黑樹保證了查詢效率,甚至取消了reentrantlock(可重入鎖),改成synchronized


相關文章