Java集合—HashMap初始化容量带大小设置成多少合适

1.HashMap扩容机制

HashMap有扩容机制,就是当达到扩容条件时会进行扩容, HashMap的扩容条件就是当HashMap中的元素个数(size)超过临界值(threshold)时就会进行扩容,HashMap中,threshold = LOAD_FACTOR * CAPACITY
所以,如果我们没有设置初始容量大小,随着元素的不断增加,HashMap会发生多次扩容,而HashMap中的扩容机制决定了每次扩容都需要重建hash表,是非常影响性能的。
所以,首先可以明确的是,我们建议开发者在创建HashMap的时候指定初始化容量。并且《阿里巴巴开发手册》中也是这么建议的:
在这里插入图片描述

2.HashMap创建初始化容量大小多少合适

那么,既然建议我们集合初始化的时候,要指定初始值大小,那么我们创建HashMap的时候,到底指定多少合适呢?
有些人会自然想到,我准备塞多少个元素我就设置成多少呗。比如我准备塞7个元素,那就new HashMap(7)。
但是,这么做不仅不对,而且以上方式创建出来的Map的容量也不是7。因为,当我们使用HashMap(int initialCapacity)来初始化容量的时候,HashMap并不会使用我们传进来的initialCapacity直接作为初始容量。
jdk1.8 源码如下:
Java集合—HashMap初始化容量带大小设置成多少合适_第1张图片
Java集合—HashMap初始化容量带大小设置成多少合适_第2张图片
Java集合—HashMap初始化容量带大小设置成多少合适_第3张图片
JDK会默认帮我们计算一个相对合理的值当做初始容量。所谓合理值,其实是找到第一个比用户传入的值大的2的幂。
也就是说,当我们new HashMap(7)创建HashMap的时候,JDK会通过计算,帮我们创建一个容量为8的Map;当我们new HashMap(9)创建HashMap的时候,JDK会通过计算,帮我们创建一个容量为16的Map。
但是,这个值看似合理,实际上并不尽然。因为HashMap在根据用户传入的capacity计算得到的默认容量,并没有考虑到loadFactor这个因素,只是简单机械的计算出第一个大约这个数字的2的幂。
也就是说,如果我们设置的默认值是7,经过JDK处理之后,HashMap的容量会被设置成8,但是,这个HashMap在元素个数达到 8*0.75 = 6的时候就会进行一次扩容,这明显是我们不希望见到的。
那么,到底设置成什么值比较合理呢?
这里我们可以参考JDK8中putAll方法中的实现的,这个实现在guava(21.0版本)也被采用。
这个值的计算方法就是:

 float ft = ((float)s / loadFactor) + 1.0F;

Java集合—HashMap初始化容量带大小设置成多少合适_第4张图片
Java集合—HashMap初始化容量带大小设置成多少合适_第5张图片
比如我们计划向HashMap中放入7个元素的时候,我们通过expectedSize / 0.75F + 1.0F计算,7/0.75 + 1 = 10 ,10经过JDK处理之后,会被设置成16,这就大大的减少了扩容的几率。

你可能感兴趣的:(java,集合,java)