HashMap的數據結構(一)


JDK1.8 以前HashMap的實現是 數組+鏈表

JDK1.8 開始HashMap的實現是 數組+鏈表+紅黑樹,如下圖:

 

HashMap類中有兩個常量:

static final int TREEIFY_THRESHOLD = 8;
static final int UNTREEIFY_THRESHOLD = 6;

  

當鏈表中節點數量大於等於TREEIFY_THRESHOLD時,鏈表會轉成紅黑樹。

當鏈表中節點數量小於等於UNTREEIFY_THRESHOLD時,紅黑樹會轉成鏈表。

為什么TREEIFY_THRESHOLD的默認值被設定為8?

HashMap中有這樣一段注釋

    /* 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). And when they become too small (due to
     * removal or resizing) they are converted back to plain bins.  In
     * usages with well-distributed user hashCodes, tree bins are
     * rarely used.  Ideally, under random hashCodes, the frequency of
     * nodes in bins follows a Poisson distribution
     * (http://en.wikipedia.org/wiki/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
     */

意思就是HashMap節點分布遵循泊松分布,按照泊松分布的計算公式計算出了鏈表中元素個數和概率的對照表,可以看到鏈表中元素個數為8時的概率已經非常小。

另一方面紅黑樹平均查找長度是log(n),長度為8的時候,平均查找長度為3,如果繼續使用鏈表,平均查找長度為8/2=4,這才有轉換為樹的必要。鏈表長度如果是小於等於6,6/2=3,雖然速度也很快的,但是鏈表和紅黑樹之間的轉換也很耗時。還有選擇6和8,中間有個差值7可以有效防止鏈表和樹頻繁轉換。

 

下一節詳細講解HashMap的Put方法流程。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM