首页 > 互联资讯 > 技术交流  > 

HashMap 的构造方法

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 的构造方法