美文网首页
HashMap容量的初始化

HashMap容量的初始化

作者: 善思者_tin | 来源:发表于2020-03-02 09:57 被阅读0次

一、概述

我们使用idea安全插件检测出hashMap容量需要进行初始化,因此本篇文章就探讨该内容,到底应不应该设置HashMap的默认容量?如果真的要设置HashMap的初始容量,我们应该设置多少?

二、为什么要设置HashMap的初始化容量

先看《阿里巴巴开发手册》这样介绍到:

【推荐】集合初始化时,指定集合初始值大小。 说明:HashMap使用HashMap(int initialCapacity) 初始化。

现进行测试在不指定初始化容量和指定初始化容量的情况下性能情况如何(JDK 版本不一样,生成的结果可能不相同,以下是jdk1.8.0_181测试所生成的结果)。

public static void main(String[] args) {

int million =1000000;

Map map =new HashMap<>();

long s1 = System.currentTimeMillis();

for (int i =0; i < million; i++) {

map.put(i, i);

}

long s2 = System.currentTimeMillis();

System.out.println("未初始化容量,耗时 : " + (s2 - s1));

Map mapOne =new HashMap<>(million /2);

long s5 = System.currentTimeMillis();

for (int i =0; i < million; i++) {

mapOne.put(i, i);

}

long s6 = System.currentTimeMillis();

System.out.println("初始化容量500000,耗时 : " + (s6 - s5));

Map mapTwo =new HashMap<>(million);

long s3 = System.currentTimeMillis();

for (int i =0; i < million; i++) {

mapTwo.put(i, i);

}

long s4 = System.currentTimeMillis();

System.out.println("初始化容量为1000000,耗时 : " + (s4 - s3));

}

测试结果

从结果中,我们可以知道,在已知HashMap中将要存放的KV个数的时候,设置一个合理的初始化容量可以有效的提高性能。

当然,以上结论也是有理论支撑的。深入理解HashMap底层原理我们知道,HashMap有扩容机制,就是当达到扩容条件时会进行扩容。HashMap的扩容条件就是当HashMap中的元素个数(size)超过临界值(threshold)时就会自动扩容。在HashMap中,threshold = loadFactor * capacity。

所以,如果我们没有设置初始容量大小,随着元素的不断增加,HashMap会发生多次扩容,而HashMap中的扩容机制决定了每次扩容都需要重建hash表,是非常影响性能的。

从上面的代码示例中,我们还发现,同样是设置初始化容量,设置的数值不同也会影响性能,那么当我们已知HashMap中即将存放的KV个数的时候,容量设置成多少为好呢?

备注:

JDK1.8初始化容量和负载因子参考如下:

private static final int initCapacity =11;

private static final double loadFactor =0.75;

三、HashMap容量的初始化

不管是Jdk 1.7还是Jdk 1.8,计算初始化容量的算法其实是如出一辙的,主要代码如下:

static final int tableSizeFor(int cap) {

int n = cap -1;

n |= n >>>1;

n |= n >>>2;

n |= n >>>4;

n |= n >>>8;

n |= n >>>16;

return (n <0) ?1 : (n >=MAXIMUM_CAPACITY) ?MAXIMUM_CAPACITY : n +1;

}

备注:e右移1位: e>>1 :相当于除以2然后取整。

上面的算法目的挺简单,就是:根据用户传入的容量值(代码中的cap),通过计算,得到第一个比他大的2的幂并返回。

聪明的读者们,如果让你设计这个算法你准备如何计算?如果你想到二进制的话,那就很简单了。举几个例子看一下:

  正例:initialCapacity = (需要存储的元素个数 / 负载因子) + 1。注意 负载因子(即loader factor)默认为 0.75,如果 暂时无法 确定 初始值大小,请设置为 16(即默认值)。 

   反例: HashMap需要 放置 1024个元素, 由于 没有设置容量 初始大小,随着元素不断增加容 量 7次被迫扩大, resize需要重建 hash表,严重影响性能。 

详见:https://mp.weixin.qq.com/s?__biz=MzI3NzE0NjcwMg==&mid=2650121359&idx=1&sn=c63d62be1a36db675c62e341044f10e0&chksm=f36bb9aec41c30b8b369428db1286d3de9bc04675057cde49632f3ba50db2d0a69451d6ec080&mpshare=1&scene=1&srcid=0529kU8fMyKTUrpKDwaLMJc6#rd

相关文章

  • HashMap

    Q: HashMap什么时候会进行扩容?HashMap在初始化时可以给定初始容量和负载因子,默认的初始容量和负载因...

  • HashMap容量的初始化

    一、概述 我们使用idea安全插件检测出hashMap容量需要进行初始化,因此本篇文章就探讨该内容,到底应不应该设...

  • 面试流水(二)

    arraylist和hashmap容易混淆的点 初始化 arraylist初始化默认容量是10,扩容条件是放不下才...

  • 关于HashMap容量的初始化,还有这么多学问?

    为什么要设置HashMap的初始化容量 我们之前提到过,《阿里巴巴Java开发手册》中建议我们设置HashMap的...

  • HashMap的最大容量为什么是2的30次方

    HashMap默认容量 看过HashMap源代码的同学都知道,HashMap有默认的最小容量和最大容量,最小容量是...

  • HashMap的最大容量为什么是2的30次方

    HashMap默认容量 看过HashMap源代码的同学都知道,HashMap有默认的最小容量和最大容量,最小容量是...

  • HashMap初始化的四种构造方法

    HashMap初始化的四种构造方法 一、HashMap() 使用默认初始容量16与默认负载因子0.75构造一个空的...

  • HashMap源码之构造函数--JDK1.8

    构造函数 变量解释 capacity,表示的是hashmap中桶的数量,初始化容量initCapacity为16,...

  • HashMap:如何进行扩容?

    在说明hashMap如何进行扩容之前,先说下为什么要进行扩容?是因为hashMap初始化的容量不够用了吗?不是,是...

  • java集合之Map接口

    Map集合中常用的方法 直接举栗子 Properties HashMap默认初始化容量是16,默认加载因子0.75...

网友评论

      本文标题:HashMap容量的初始化

      本文链接:https://www.haomeiwen.com/subject/tvtdfhtx.html