• 说在前面

    ​ 在HashMap中,默认创建的数组长度是16,也就是哈希桶个数为16,当添加key-value的时候,会先计算出他们的哈希值(h = hash),然后用return h & (length-1)就可以算出一个数组下标,这个数组下标就是键值对应该存放的位置。

    ​ 但是,当数据较多的时候,不同键值对算出来的hash值相同,而导致最终存放的位置相同,这就是hash冲突,当出现hash冲突的时候,该位置的数据会转变成链表的形式存储,但是我们知道,数组的存储空间是连续的,所以可以直接使用下标索引来查取,修改,删除数据等操作,而且效率很高。而链表的存储空间不是连续的,所以不能使用下标 索引,对每一个数据的操作都要进行从头到尾的遍历,这样会使效率变得很低,特别是当链表长度较大的时候。为了防止链表长度较大,需要对数组进行动态扩容。

    ​ 数组扩容需要申请新的内存空间,然后把之前的数据进行迁移,扩容频繁,需要耗费较多时间,效率降低,如果在使用完一半的时候扩容,空间利用率就很低,如果等快满了再进行扩容,hash冲突的概率增大!!那么什么时候开始扩容呢???

    ​ 为了平衡空间利用率和hash冲突(效率),设置了一个加载因子(loadFactor),并且设置一个扩容临界值(threshold = DEFAULT_INITIAL_CAPACITY * loadFactor),就是说当使用了16*0.75=12个数组以后,就会进行扩容,且变为原来的两倍。

  • 为什么加载因子是0.75呢?

    先看一段源码注释:

    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

    大概意思就是说,在理想情况下,使用随机哈希码,节点出现的频率在hash桶中遵循泊松分布,同时给出了桶中元素个数和概率的对照表。从上面的表中可以看到当桶中元素到达8个的时候,概率已经变得非常小,也就是说用0.75作为加载因子,每个碰撞位置的链表长度超过8个的概率达到了一百万分之一。

版权声明:本文为coding-996原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/coding-996/p/12053721.html