HashMap 为什么在链表长度为 8 的时候转红黑树,为啥不能是 9 是 10?
這個問題是在面試某公司的時候面試官提的問題,當時沒回答上來。歸根到底還是因為自己復習基礎的時候還不夠仔細,也缺乏思考。
首先
我覺得需要確認一下,是不是隨便什么情況下只要滿足了鏈表長度為8就轉紅黑樹呢?答案自然不是,為什么不是,看代碼:
/*** Replaces all linked nodes in bin at index for given hash unless* table is too small, in which case resizes instead.*/final void treeifyBin(Node<K,V>[] tab, int hash) {int n, index; Node<K,V> e;if (tab == null || (n = tab.length) < MIN_TREEIFY_CAPACITY)resize();......}這是HashMap轉紅黑樹的方法代碼,可以看到,如果此時的HashMap的長度是小于MIN_TREEIFY_CAPACITY的或者為空,則進行擴容操作,而不是轉紅黑樹,這其實也是容易忽略的點。
為什么要轉紅黑樹?
回答自然很簡單,因為鏈表是取一個數需要遍歷鏈表,復雜度為O(N),而紅黑樹為O(logN)唄,那么問題來了
為什么不直接使用紅黑樹,而是要先使用鏈表實在不行再轉紅黑樹呢?
答案自然要在源碼和注釋里找:在HashMap類中第174行左右有描述:
Because TreeNodes are about twice the size of regular nodes, weuse them only when bins contain enough nodes to warrant use(see TREEIFY_THRESHOLD)“因為樹節點的大小是鏈表節點大小的兩倍,所以只有在容器中包含足夠的節點保證使用才用它”,顯然盡管轉為樹使得查找的速度更快,但是在節點數比較小的時候,此時對于紅黑樹來說內存上的劣勢會
超過查找等操作的優勢,自然使用鏈表更加好,但是在節點數比較多的時候,綜合考慮,紅黑樹比鏈表要好。
為什么是8,而不是9不是10?
其實當時想回答面試官這是基于統計的結果,但是心里很虛還是沒有說,再回頭看看源碼的描述:
Ideally, under random hashCodes, the frequency of nodes in bins follows a Poisson distribution with a parameter of about 0.5 on average for the default resizing threshold of 0.75, although with a large variance because of resizing granularity. Ignoring variance, the expected occurrences of list size k are (exp(-0.5) * pow(0.5, k) / factorial(k)). The first values are:0: 0.606530661: 0.303265332: 0.075816333: 0.012636064: 0.001579525: 0.000157956: 0.000013167: 0.000000948: 0.00000006more: less than 1 in ten million理想情況下,在隨機哈希碼下,哈希表中節點的頻率遵循泊松分布,而根據統計,忽略方差,列表長度為K的期望出現的次數是以上的結果,可以看到其實在為8的時候概率就已經很小了,再往后調整并沒有很大意義。
更多 Java 原創文章,請關注我微信公眾號 「Java中文社群」
總結
以上是生活随笔為你收集整理的HashMap 为什么在链表长度为 8 的时候转红黑树,为啥不能是 9 是 10?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 史上最详细nodejs版本管理器nvm的
- 下一篇: 聊一聊开发常用小工具