先来问一下:Java中使用HashMap指定初始化容量或负载因子,性能一定会更好吗?
可参考如下文章
Java中使用HashMap时指定初始化容量性能一定会更好吗?_java hashmap 初始大小使用会越界吗-CSDN博客
初始化hashMap时,实际项目中可能会出现不指定容量反而比指定容量更快,原因是当我们用无参构造new HashMap时,这个时候只有一句简单的代码
public HashMap() {
this.loadFactor = DEFAULT_LOAD_FACTOR; // all other fields defaulted
}
而使用带参构造时,不管用初始化容量还是初始化容量与负载因子,都会做参数检查,导致额外的性能负担,所以导致数据量较小时指定容量时反而性能更差一些。
建议:大多数情况下,建议指定容量,类似的还有ArrayList也建议指定容量。
言归正传
先举例说明 HashMap 使用的时候指定容量 错误用法;
示例1:Map<String, String> map = new HashMap<>(6);
示例2:Map<String, String> map = new HashMap<>(userList.size());
示例3:Map<String, String> map = new HashMap<>(4);
示例1:当我们指定的容量不是2的n次幂时,容量会默认变成2的n次幂,也就是会变成8
示例2:我们期望是Map只需要放userList.size()数量的元素,但因为负载因子使用了默认的0.75,导致在put时,实际上还会进行扩容
示例3:同样,我们期望放4个元素进去,但因为负载因子使用了默认的0.75,导致在put时,实际上还会进行扩容
再来问一下,当我们当我们使用默认的无参构造new HashMap时,插入第几个元素的时候会再次扩容?
首先我们看到HashMap中有个capacity的方法,利用反射,获取HashMap长度
结论在图中
最后:当我们想使用HashMap想插入5个元素时,例new HashMap<>(5),指定的容量不是2的指数倍,这个时候容量会自动变成8。因为我们已知该Map只需要插入5个元素,这个时候负载因子可以用5/8=0.625,也可以直接用1。我懒得计算,负载因子一般直接用1
建议:当我们指定HashMap的容量时,建议也指定负载因子。例new HashMap<>(5)改成new HashMap<>(8,1)