简述 HashMap 扩容机制

HashMap基础

【注意】以下内容只是针对 JDK1.8

HashMap继承了AbstractMap类,实现了Map,Cloneable,Serializable接口。

其使用 hash 算法来决定元素的存储,hash 表包含如下属性。

  • 容量(capacity):hash 表数组的大小,默认为16;
  • 初始化容量(initial capacity):创建 hash 表时指定的初始容量;
  • 尺寸(size):当前 hash 表中记录的数量;
  • 负载(load):负载等于 “ size / capacity ”。负载为 0 时,表示空的 hash 表。轻负载的 hash 表具有冲突少、适宜插入和查询的特点。(但太小的话,又会增加占用的内存开销)。
  • 负载因子(load factor):决定 hash 表的最大填满程度,范围是 0~1,默认为 0.75 。

当 hash 表的负载达到了指定的 “负载因子” 值时,hash 表就会加倍扩容,并将原有的对象重新分配,放入新的表中,这称为 rehashing 。rehashing 过程很复杂,而已非常消耗性能,所以指定一个合适的 “负载因子” 值很重要。

当 size / capacity > 负载因子,即 size(当前记录数) > 负载因子 * capacity(容量) 时,hash 会扩容。

HashMap的容量,默认是16

/**
 * The default initial capacity - MUST be a power of two.
 */
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16

HashMap的加载因子,默认是0.75

/**
 * The load factor used when none specified in constructor.
 */
static final float DEFAULT_LOAD_FACTOR = 0.75f;

当HashMap中元素数超过 容量 * 加载因子 时,HashMap会进行扩容。

扩容多大?

HashMap 扩容是为当前容量 * 2,也就是成倍扩容。

【问题1】为什么每次扩容的倍数是2,而不是1.5或者2.5 ?

理论上,扩容倍数用多少都行,1.5, 2.5 ,3.5都可以的,都能实现HashMap。

实际上,HashMap选用了2倍,是为了做一个优化。

因为计算哈希值的时候是使用取模运算,而HashMap的开发者想要优化下这个取模运算的速度,那么他就需要把HashMap内部的数组长度固定为 2^n 的长度了,也就是说HashMap里面的数组的长度,始终都是2的n次幂。为了实现这个效果,它的扩容因子很自然就是2倍了。

原文地址:https://www.cnblogs.com/luler/p/15271392.html