HashMap 的构造方法
- 技术交流
- 2024-09-25 20:34:02
HashMap 有 4 个构造方法:
1、带初始容量和装载因子的构造方法: 检查初始容量和装载因子的有效性,并计算初始容量最近的 2 的整数幂;
2、带初始容量的构造方法: 使用默认负载因子 0.75 调用上一个构造方法;
3、无参构造方法: 设置默认装载因子 0.75;
4、带 Map 参数的构造方法: 设置默认装载因子 0.75,并逐个添加 Map 中的映射关系。
可以看到,在 HashMap 的构造方法中并没有创建底层数组,而是延迟到 put 操作中触发的 resize 扩容操作中创建数组。另外,在可以已知存储的数据量时,可以在构造器中预先设置初始容量,避免在添加数据的过程中多次触发扩容。
// 带初始容量和装载因子的构造方法
public HashMap(int initialCapacity, float loadFactor) {
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal initial capacity: " + initialCapacity);
if (initialCapacity > MAXIMUM_CAPACITY)
// 最大容量限制
initialCapacity = MAXIMUM_CAPACITY;
if (loadFactor <= 0 || Float.isNaN(loadFactor))
throw new IllegalArgumentException("Illegal load factor: " + loadFactor);
// 装载因子上限
this.loadFactor = loadFactor;
// 扩容阈值(此处不是真正的阈值,仅仅只是将传入的容量转化最近的 2 的整数幂,该阈值后面会重新计算)
this.threshold = tableSizeFor(initialCapacity);
}
// 带初始容量的构造方法
public HashMap(int initialCapacity) {
this(initialCapacity, DEFAULT_LOAD_FACTOR /*0.75*/);
}
// 无参构造方法
public HashMap() {
this.loadFactor = DEFAULT_LOAD_FACTOR /*0.75*/;
}
// 带 Map 的构造方法
public HashMap(Map<? extends K, ? extends V> m) {
this.loadFactor = DEFAULT_LOAD_FACTOR /*0.75*/;
// 疑问 7:为什么不使用 Arrays 工具类整体复制,而是使用 putMapEntries 批量添加?
// 批量添加
putMapEntries(m, false);
}
// 疑问 8:tableSizeFor() 的函数体解释一下?
// 获取最近的 2 的整数幂
static final int tableSizeFor(int cap) {
// 先减 1,让 8、16 这种本身就是 2 的整数幂的容量保持不变
// 在 ArrayDeque 中没有先减 1,所以容量 8 会转为 16
int n = cap - 1;
n |= n >>> 1;
n |= n >>> 2;
n |= n >>> 4;
n |= n >>> 8;
n |= n >>> 16;
return (n < 0) ? 1 /*tableSizeFor() 方法外层已经检查过超过 2^30 的值,应该不存在整型溢出的情况*/
: (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
}
HashMap 的构造方法由讯客互联技术交流栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“HashMap 的构造方法”