HashMap介紹
基本實現原理
- jdk1.7是數組+鏈表實現。
- jdk1.8是數組+鏈表+紅黑樹實現,鏈表長度達到8會轉成紅黑樹。
一些擴展知識
- 為啥使用紅黑樹不用AVL樹:紅黑樹的平衡性相對avl來說稍差,但是旋轉操作更少,插入和刪除效率更高。
- 為啥每次擴容2倍:方便位運算,以及降低hash沖突(初始容量是16)。
- 為啥并發下會出現死循環:1.7版本之前hash沖突是使用頭插法,在多線程并發同時擴容時可能會出現死循環。1.8版本使用尾插法解決。
ConcurrentHashMap介紹
基本實現原理
- jdk1.7采用分段鎖,內部是是個Segment數組,Segment里面是一個數組+鏈表。Segment繼承了ReentrantLock。往map里面put數據的時候,會先定位數據在哪個Segment上,然后對這個Segment進行加鎖
- jdk1.8是采用cas+synchronized,在沒有hash沖突時,使用cas將元素放到數組對應的位置上中。當出現hash沖突時,會使用synchronized對數組中對應位置上的node節點加鎖。
一些擴展知識
- 擴容加速:擴容時其它線程寫操作會協助擴容,而不是阻塞等待
- 計數器優化:采用了longadder的思想,空間換時間,將個數分散到一個數組中,不同線程對不同的槽位進行累加,減少并發度,從而達到更高的性能
- 為什么key和val不允許為null:在多線程并發情況下,null會帶來二義性。當我們通過get獲取到key的value為null時,你無法判斷是put的時候value為null,還是這個key本身就不在map里面