原由:node
這個問題是在面試某公司的時候面試官提的問題,當時沒回答上來。歸根到底仍是由於本身複習基礎的時候還不夠仔細,也缺少思考。面試
首先less
我以爲須要確認一下,是否是隨便什麼狀況下只要知足了鏈表長度爲8就轉紅黑樹呢?答案天然不是,爲何不是,看代碼:dom
/** * 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的或者爲空,則進行擴容操做,而不是轉紅黑樹,這其實也是容易忽略的點。spa
爲何要轉紅黑樹?code
回答天然很簡單,由於鏈表是取一個數須要遍歷鏈表,複雜度爲O(N),而紅黑樹爲O(logN)唄,那麼問題來了blog
爲何不直接使用紅黑樹,而是要先使用鏈表實在不行再轉紅黑樹呢?內存
答案天然要在源碼和註釋裏找:在HashMap類中第174行左右有描述:源碼
Because TreeNodes are about twice the size of regular nodes, we
use them only when bins contain enough nodes to warrant use
(see TREEIFY_THRESHOLD)
「由於樹節點的大小是鏈表節點大小的兩倍,因此只有在容器中包含足夠的節點保證使用才用它」,顯然儘管轉爲樹使得查找的速度更快,可是在節點數比較小的時候,此時對於紅黑樹來講內存上的劣勢會hash
超過查找等操做的優點,天然使用鏈表更加好,可是在節點數比較多的時候,綜合考慮,紅黑樹比鏈表要好。
爲何是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.60653066 1: 0.30326533 2: 0.07581633 3: 0.01263606 4: 0.00157952 5: 0.00015795 6: 0.00001316 7: 0.00000094 8: 0.00000006 more: less than 1 in ten million
理想狀況下,在隨機哈希碼下,哈希表中節點的頻率遵循泊松分佈,而根據統計,忽略方差,列表長度爲K的指望出現的次數是以上的結果,能夠看到其實在爲8的時候機率就已經很小了,再日後調整並
沒有很大意義。