hashmap知識點
初始容量 16 裝載因子 0.75 預設限制擴容數 64 轉換紅黑樹閾值 8 轉換鍊錶閾值 6
當鍊表長度大於8 鍊錶轉為紅黑樹(前提是hashmap容量達到64) 當紅黑樹中的元素個數小於6 再轉回鍊錶(前提是根節點或者子節點為空)。
(其實不準確:
2.1 大於8,是先考慮table陣列擴容,達到限制擴容64後,才轉換
2.2 只有在resize()時根據閥值轉換;remove()時會先判斷根節點或者子節點是否為空,10 )
選擇8 和6 的原因:1.時間複雜度 2.如果hashcode離散性好,鍊錶數量達到8個的概率極低,基本不會用到紅黑樹; 而如果離散性不好很隨機,hash碰撞嚴重,則轉換為樹的概率大。
table陣列(也成桶),每次擴容都以2的整數次冪擴容
table 的 index 下標計算方式
int index =key.hashcode()&(length-1);
//length=16,32,64… 轉換成二進位制就是 1111,11111… 與運算的時候保證index都在範圍內,
而且只要key足夠分散 均勻,獲得的index就減少重複,從而減少hash碰撞,提高查詢效率。
初始值為16 原因:減少hash碰撞,小了容易頻繁擴容影響效能,大了浪費資源,綜合考慮16最佳。
紅黑樹知識點:
(自平衡即非完全平衡的)二叉查詢樹
1.1 每個節點都有二個子節點 ,
1.2 左節點 小於 父節點 ,右節點 大於父節點
節點有二個顏色 黑 或 紅
根節點是黑色
所有的葉子節點都是黑色(葉子節點 是nil 節點,一般不顯
紅色節從任乙個節點 到其每個葉子節點 的所有簡單路徑 都包含有相同個數的黑色節點
點 的二個子節點 都是黑色子節點 。(即 不能有連續的二個紅色父子節點)
紅黑樹的二大操作:
1.recolor(重新標記為黑色或者紅色)
2.rotation(旋轉,這個是平衡關鍵)
具體操作:
每新插入乙個節點x,標記 為紅色(因為如果是不為空的紅黑樹那必然是已經平衡的,新插入黑色必定不平衡,所以直接插入紅色)
如果x是根節點root,標記為黑色。
如果x的父parent節點不是黑色,同時x也不是root;
3.1 如果x 的uncle(叔叔即父節點的兄弟節點) 是紅色
3.1.1 將 parent 和 uncle 標記為黑色
3.1.2 將grand parent (祖父節點即爺爺節點,非root) 標記為紅色
3.1.3 讓 x 的顏色 和 祖父節點 相同,(其實上一步已經一樣了),然後重複步驟 2、3;
3.2 如果 x uncle 節點是黑色,分四種清空
3.2.1 左左(父節點(父節點是左節點)的左子節點)
x 父節點 祖父節點 這三個當成乙個小的紅黑樹(像一條直線,繩子)
提起 父節點,祖父節點下降,然後把 父節點和 祖父節點 顏色互換 ,這樣形成了乙個新的平衡的紅黑樹
3.2.2 左右(父節點(父節點是左節點)的右子節點)
想辦法變成和 左左一樣的情況就好了,這裡用到左旋: 把 x 和 父節點 替換,父節點變成 x 的左子節點,剩下和左左一樣,提繩子 ,互換顏色。
3.2.3 右右(uncle節點(uncle是右節點)的右子節點)
提繩子,互換顏色
3.2.4 右左(uncle節點(uncle是右節點)的左子節點)
右旋:x 和父節點互換 ,把父節點稱為右子節點,變成和右右一樣,然後 提繩子,互換顏色。
啥不用做,如果父節點是黑色的,x是紅色的 直接插就完事了,已經平衡了。
從HashMap看紅黑樹
樹上的節點要麼是紅色,要麼是黑色 根節點是黑色 每個葉子節點都是黑色的 所有的葉子節點都是null節點 紅色節點的子節點都是黑色的 任意乙個節點到其子孫葉子節點的黑色節點的數量是相等的。下面是乙個紅黑樹的圖示 從任意節點 不含該節點 到達乙個葉節點的任意一條簡單路徑上的黑色節點個數稱為該節點的黑高 ...
紅黑樹知識總結
紅黑樹 red black tree 是一種自平衡二叉查詢樹,所有資料塊都儲存在節點中,在進行插入和刪除操作時通過特定操作保持二叉查詢樹的平衡,從而獲得較高的查詢效能,它雖然是複雜的,但它的最壞情況執行時間也是非常良好的,並且在實踐中是高效的 它可以在o log n 時間內做查詢,插入和刪除,這裡的...
HashMap總結(不包括紅黑樹)
hashmap是用來存放key value的容器,底層是使用陣列 鍊錶 紅黑樹 實現的 節點少時 預設是untreeify threshold 6值 用鍊錶,多時 預設是 treeify threshold 8 用紅黑樹,樹化容量為min treeify capacity,預設是64。成員變數 構造...