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

  • 相关阅读:
    简明Python3教程 12.问题解决
    简明Python3教程 11.数据结构
    【SPOJ 694】Distinct Substrings
    【codeforces Manthan, Codefest 17 C】Helga Hufflepuff's Cup
    【CF Manthan, Codefest 17 B】Marvolo Gaunt's Ring
    【CF Manthan, Codefest 17 A】Tom Riddle's Diary
    【SPOJ 220】 PHRASES
    【POJ 3261】Milk Patterns
    【POJ 3294】Life Forms
    【POJ 1226】Substrings
  • 原文地址:https://www.cnblogs.com/coding-996/p/12053721.html
Copyright © 2011-2022 走看看