JDK1.8 HashMap为何在链表长度为8的时候转红黑树,为啥不能是9是10

原由: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的时候几率就已经很小了,再日后调整并

没有很大意义。

相关文章
相关标签/搜索