美文网首页源码解析JDK--HashMap源码阅读
JDK1.8 HashMap源码解读 一一 构造方法

JDK1.8 HashMap源码解读 一一 构造方法

作者: 从你说谎 | 来源:发表于2018-03-26 17:59 被阅读41次
  • public HashMap()
/**
 * Constructs an empty <tt>HashMap</tt> with the default initial capacity
 * (16) and the default load factor (0.75).
 */
public HashMap() {
    this.loadFactor = DEFAULT_LOAD_FACTOR; // all other fields defaulted
}

可以看到, 如果调用不带参数的构造方法, HashMap将会初始化一个默认的负载因子, 值为0.75, 这个负载因子是表示Map空间填满程度, 当Map存储的元素达到阀值, 则会自动扩容.

  • public HashMap(int initialCapacity)
/**
 * Constructs an empty <tt>HashMap</tt> with the specified initial
 * capacity and the default load factor (0.75).
 *
 * @param  initialCapacity the initial capacity.
 * @throws IllegalArgumentException if the initial capacity is negative.
 */
public HashMap(int initialCapacity) {
    this(initialCapacity, DEFAULT_LOAD_FACTOR);
}

注释已经写得很清楚了, 使用指定的初始容量和默认负载因子(0.75)构造一个空的 HashMap, 将参数和默认的负载因子传入另一个构造方法, 我们直接来看这个 this 指向的另一个构造方法.

  • public HashMap(int initialCapacity, float loadFactor)
/**
 * Constructs an empty <tt>HashMap</tt> with the specified initial
 * capacity and load factor.
 *
 * @param  initialCapacity the initial capacity
 * @param  loadFactor      the load factor
 * @throws IllegalArgumentException if the initial capacity is negative
 *         or the load factor is nonpositive
 */
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;
    this.threshold = tableSizeFor(initialCapacity);
}

首先不允许你将Map的初始容量设为负数, 否则直接抛异常了. 然后判断初始容量是否大于最大可设置容量, 如果大于则直接用最大可设置容量覆盖掉传进来的初始容量, 再去判断负载因子是否符合条件, 不符合则抛出异常.
如果都没问题, 则将负载因子赋值, 然后调用 static final int tableSizeFor(int cap) 方法.

 /**
 * Returns a power of two size for the given target capacity.
 */
static final int tableSizeFor(int cap) {
    int n = cap - 1;
    n |= n >>> 1;
    n |= n >>> 2;
    n |= n >>> 4;
    n |= n >>> 8;
    n |= n >>> 16;
    return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
}

这方法什么意思呢, 就是为了算出大于等于 initialCapacity 的最小的2的幂, 然后将值赋给 threshold 变量. 而这个 threshold 正是用来判断Map是否需要扩容的


开始的时候会觉得下面这段代码是错的
 this.threshold = tableSizeFor(initialCapacity);

threshold 不应该是直接赋值的, 我们知道, 当Map中的元素个数大于(Map的容量 * 负载因子)时, Map才应该扩容, 所以, 触发Map扩容的阀值应该是如下代码

this.threshold = tableSizeFor(initialCapacity) * this.loadFactor;

但是,请注意,在构造方法中,并没有对table这个成员变量进行初始化,table的初始化被推迟到了put方法中,在put方法中会对threshold重新计算,具体解读, 在下节见分晓.

相关文章

网友评论

    本文标题:JDK1.8 HashMap源码解读 一一 构造方法

    本文链接:https://www.haomeiwen.com/subject/fhyrcftx.html