面試集錦(十二)hashMap

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來保證併發安全性code

1.8以後在數據結構上作了改動,超過閾值後採用紅黑樹保證了查詢效率,甚至取消了reentrantlock(可重入鎖),改爲synchronized對象

相關文章
相關標籤/搜索