1、JDK 8 HashMap為啥要引入紅黑樹?
當HashMap 的 key 衝突過多時,比如我們使用了不好的 hash 算法,導致key衝突率極高,鏈表裏會有很多數據。
但是鏈表的查找性能很差,所以引入紅黑樹是為了優化查詢性能。
2、JDK 8 HashMap為啥不直接用紅黑樹?
因為樹節點所佔用的空間是普通節點的兩倍,所以只有當節點足夠多的時候,才會使用樹節點。
也就是説,最開始使用鏈表的時候,鏈表是比較短的,空間佔用也是比較少的,查詢性能都差不多。
但是當鏈表越來越長,鏈表查詢越來越慢,這時候才會捨棄鏈表而使用紅黑樹,以空間換時間。
所以沒有必要一開始就用紅黑樹,另外,鏈表較長的情況非常少見。
一開始就使用紅黑樹反而會導致所有的情況都會佔用比鏈表大2倍的空間,適得其反,這也是一種平衡的策略。
3、為什麼鏈表長度達到8?
因為達到8個元素的時候,概率已經很低了。此時樹化,性價比會很高。
既不會因為鏈表太長(8)導致複雜度加大,也不會因為概率太高導致太多節點樹化。
4、為什麼紅黑樹轉鏈表的閾值為6?
主要是因為,如果也將該閾值設置於8,那麼當hash碰撞在8時,會反生鏈表和紅黑樹的不停相互激盪轉換。中間有個差值7可以防止鏈表和樹之間的頻繁轉換。
假設一下:
如果設計成鏈表個數超過8則鏈表轉換成樹結構,鏈表個數小於8則樹結構轉換成鏈表,
如果HashMap不停的插入,刪除元素,鏈表個數在8左右徘徊,就會頻繁的發生紅黑樹轉鏈表,鏈表轉紅黑樹,效率會很低下。
5、putVal 方法主要做了這麼幾件事情
當桶數組 table 為空時,resize()初始化 table查找要插入的鍵值對是否已經存在,
onlyIfAbsent如果為false且oldValue等於null 則覆蓋舊值。
如果不存在,則將鍵值對鏈入鏈表中,如果鏈表長度達到了8,且數組長度小於64,那麼就重新散列。
如果大於64,則創建紅黑樹判斷鍵值對數量是否大於閾值,大於的話則進行擴容操作。