JDK7中當我們用頭插法 對舊table
數據重定位到新table
的時候我們知道是會行程環的,環產生的核心函數transfer
如下,其中重點關注部分以標出。
- 頭插法正常情況下:
- 併發情況下,比如我有兩個線程在同時進行put數據跟擴容操作,線程1只執行了
Entry<K,V> next = e.next
就被掛起了,而線程2正常執行完畢,結果圖如下:
線程2執行完畢後線程1接着從原來的暫停處開始執行下面的語句:
通過逐步分析跟繪圖可以知道紅色部分會有環產生。JDK中HashMap是不安全的,多線程情況下要用ConcurrentHashMap。
7vs8
- 7中找
Hash
用了4次,8中只用了1次。- 7 = 數組 + 鏈表,8 = 數組 + 鏈表 + 紅黑樹
- 7中是頭插法,多線程容易造成環,8中是尾插法。
- 7的擴容是全部數據重新定位,8中是位置不變+ 移動舊size大小來實現更好些。
- 7是先判斷是否要擴容再插入,8中是先插入再看是否要擴容。
HashMap
不管78都是現場不安全的,多線程情況下記得用ConcurrentHashmap
。ConcurrentHashmap
下篇文章說。
常見問題
隨機蒐羅了一些常見HashMap
問題,如果把上述代碼都看懂了應付這些應該沒問題。
- HashMap原理,內部數據結構。
- HashMap中的put,get,remove大致過程。
- HashMap中 hash函數實現。
- HashMap如何擴容。
- HashMap幾個重要參數爲什麼這樣設定。
- HashMap爲什麼線程不安全,如何替換。
- HashMap在JDK7跟JDK8中的區別。
- HashMap中鏈表跟紅黑樹切換思路。