zoukankan      html  css  js  c++  java
  • 为什么HashMap的加载因子是0.75?

    说在前面

    ​ 在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个的概率达到了一百万分之一。

  • 相关阅读:
    Spring 实例化bean的三种方式
    Mybatis和Hibernate比较
    MyBatis学习总结(一)——MyBatis快速入门
    Java EE的十三个规范
    Python 测试代码覆盖率统计工具 coverage.py
    mysql explain执行计划详解
    Django模型的Field Types
    使程序在Linux下后台运行,程序运行前后台切换
    ubuntu中将本地文件上传到服务器
    Python-内置函数小结
  • 原文地址:https://www.cnblogs.com/coding-996/p/12053721.html
Copyright © 2011-2022 走看看