zoukankan      html  css  js  c++  java
  • Java中HashMap扩容机制思考

    1. HashMap在什么条件下扩容

    判断HashMap的数组Size大小如果超过loadFactor*capacity,就要扩容。

    相关的类属性:

    • capacity:当前数组容量,始终保持 2^n,可以扩容,扩容后数组大小为当前的 2 倍。

    • loadFactor:负载因子,默认为 0.75

      loadFactor加载因子是控制数组存放数据的疏密程度,loadFactor越趋近于1,那么 数组中存放的数据(entry)也就越多,也就越密,也就是会让链表的长度增加,loadFactor越小,也就是趋近于0,数组中存放的数据(entry)也就越少,也就越稀疏。

      loadFactor太大导致查找元素效率低,太小导致数组的利用率低,存放的数据会很分散。loadFactor的默认值为0.75f是官方给出的一个比较好的临界值

      给定的默认容量为 16,负载因子为 0.75。Map 在使用过程中不断的往里面存放数据,当数量达到了 16 * 0.75 = 12 就需要将当前 16 的容量进行扩容,而扩容这个过程涉及到 rehash、复制数据等操作,所以非常消耗性能。

    • threshold:扩容的阈值

      threshold = capacity * loadFactor,当Size>=threshold的时候,那么就要对数组扩增了。

    2. HashMap 的长度为什么是2的幂次方

    为了能让 HashMap 存取高效,尽量减少碰撞,把数据分配均匀,利用扰动函数hash方法对key进行处理得到Hash值Hash 值的范围值-2147483648到2147483647,前后加起来大概40亿的映射空间,只要哈希函数映射得比较均匀松散,一般应用是很难出现碰撞的。但问题是一个40亿长度的数组,内存是放不下的。所以这个散列值是不能直接拿来用的。用之前还要先做对数组的长度取模运算,得到的余数才能用来要存放的位置也就是对应的数组下标。这个数组下标的计算方法是“ (n - 1) & hash”。(n代表数组长度)

    取余(%)操作中如果除数是2的幂次则等价于与其除数减一的与(&)操作(也就是说 hash%length==hash&(length-1)的前提是:length 是2的 n 次方),且采用二进制位操作 &,相对于%能够提高运算效率,这就解释了 HashMap 的长度为什么是2的幂次方。

  • 相关阅读:
    C#学习历程(三)[基础概念]
    C#学习历程(二)[基础知识]
    C#学习历程(一)[基础概念]
    mvp和mvc的区别
    Java基础摘要(一)
    web前端概念摘要(一)
    Reflection_1
    后台管理_GMS_1
    模板收藏_1
    需求收藏_1
  • 原文地址:https://www.cnblogs.com/MWCloud/p/11379849.html
Copyright © 2011-2022 走看看