HashMap1 8之節點刪除分析

2022-03-31 19:05:58 字數 1927 閱讀 7997

大家一直關注的都是hashmap如何新增節點,當節點數量大於8的時候轉化為紅黑樹,否則使用鍊錶等等,但大家是否有看過刪除節點的處理邏輯呢? 今天來看看hashmap刪除節點的神來之筆

在檢視hashmap原始碼時,有個以下字段,在刪除的時候,判斷節點數量,最多在小於6的時候,會untreeifying(樹轉化為鍊錶),在點選這個欄位時發現,只有在split()方法中使用,但split()方法在resize()方法中使用,與刪除節點無關,遂去翻刪除節點的**邏輯

通過remove方法,一路進來,找到刪除節點的地方。如下圖:

我們進入removetreenode方法中,**如下:

檢視方法注釋,裡面介紹到:如果節點太少,就會把當前bin轉換成普通bin。不理解注釋沒關係,我們進入這個方法中唯一有轉化的地方。進入untreeify()方法檢視下。**如下:

噢,第一行看一下,if,else看一下,嗯,這個方法就是獲取返回了乙個列表(這些方法都是treenode類裡面的方法,所以請注意,this就是當前要操作的treenode節點)。到此明白,這個方法就是把紅黑樹轉化成鍊錶的,那麼我的就得分析分析是如何操作的了,而沒有使用到定義的全域性變數。

我們來分析分析上面這個邏輯,進入這個untreeify() 的要求是,root == null, root.right ==null, root.left==null, root.left.left==null四種情況,我們以7個節點的紅黑樹來分析,a為root節點。

所以進入這個方法主要有以下幾種情況,我們一種一種的來分析當滿足要求時,節點的個數。(這裡預設認為知道紅黑樹的5個特點,主要是黑平衡)

當這四種情況都滿足時,我們可以看出最多節點有如上圖所示個數,可以為7個。(大於8個不考慮,因為大於8會變成紅黑樹)。

1.  最多節點情況:當我們刪除節點d時,只滿足root.left.left==null這個條件,這棵樹仍可以維持紅黑樹的特點,這時的最大節點數為6.

2.  最少節點情況:當efg不存在時,在a,b,c,d中刪除任意乙個節點,都會滿足上述四種規則中的一種。則存在最少節點情況,有3個節點。

以上情況都是會將樹轉化成鍊錶,此時的節點是 3<= nodes <=6 ,由此可以看出,當節點數在小於6時,是可能轉化成鍊錶,但不是絕對情況, 所以使用定義的變數(固定數量6)也不正確。只好通過判斷去動態獲取節點數。

為什麼在小於6的時候可能轉換成鍊錶,而在大於8的時候轉化成紅黑樹?

主要通過時間查詢節點分析,紅黑樹的平均查詢時間為 log(n), 而鍊錶是o(n),平均是o(n)/2。

當節點數為8時,紅黑樹查詢時間3,鍊錶查詢時間是4, 可以看出來當紅黑樹查詢效率大於了鍊錶。(兩個函式曲線問題,當節點更多是,比紅黑樹需要的時間更多)

當節點數為6時,為什麼轉換成鍊錶,我認為主要時因為節點數太少,如果還是用紅黑樹,為了維持紅黑樹的特點,則需要翻轉,左旋,右旋,等,更消耗效能。 

為什麼不是7是轉化?

主要是為了給乙個過渡,防止頻繁轉化。 也如上圖,7個節點可能正好是乙個滿二叉樹。

HashMap1 8原始碼分析

1 hashmap的原理,內部資料結構如何?底層使用雜湊表 陣列 鍊錶 當鍊表過長 其實是大於8 的時候會將鍊錶轉換成紅黑樹,以實現n log n 的查詢。2 具體過程 對 key 求 hash 值,然後再計算 下標。如果沒有碰撞,直接放入桶中,如果碰撞了,以鍊錶的方式鏈結到後面,如果鍊錶長度超過閥...

HashMap 1 8 原始碼閱讀

一 初始化 1.無參建構函式 負載因子預設值 static final float default load factor 0.75f 指定loadfactor負載因子的值是0.75f public hashmap 2.指定初始化大小和負載因子 hashmap的最大容量 static final i...

原始碼分析 HashMap 1 8

1.0 資料結構 2.0 儲存流程 3.0 陣列元素 鍊錶節點的實現類 hashmap中的陣列元素 鍊錶節點 採用node類 實現,與jdk1.7相比只是把entry換了個名字 hashmap中的紅黑樹節點 採用treenode類 實現 紅黑樹節點 實現類 繼承自linkedhashmap.entr...