1.创建HashMap时传入初始化容量和负载系数

initialCapacity(初始化容量):顾名思义,这个参数定义了这个HashMap的初始大小;小于零会抛出非法参数异常,大于MAXIMUM_CAPACITY(2的三十次方)则默认等于2的三十次方
loadFactor(负载因子):

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);
}

threshold:当你的HashMap需要扩容时,扩容容量(添加方法put会用到此方法)

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;
}

">>>":无符号右移(相当于加一)
"|="做或运算后把值存到左边的变量("或运算":有1结果为1,全为0结果为0)
为什么要对cap做减1操作?这是为了防止cap已经是2的幂.如果cap已经是2的幂,又没有执行这个减1操作,则执行完后面的几条无符号右移操作之后,返回的capacity将是这个cap的2倍.最后+1,使之成为2的幂
非常牛的一个算法,用于找到大于等于initialCapacity的最小的2的幂(不懂的http://www.th7.cn/Program/jav... 这里不做赘述)

2.创建HashMap时只传入初始化容量

public HashMap(int initialCapacity) {
    this(initialCapacity, DEFAULT_LOAD_FACTOR);
}

默认负载因子DEFAULT_LOAD_FACTOR = 0.75f

3.创建HashMap时不传入任何参数

public HashMap() {
    this.loadFactor = DEFAULT_LOAD_FACTOR;
}

4.创建HashMap时传入一个实现了Map接口的对象,此HashMap创建后会包括此Map的所有内容

public HashMap(Map<? extends K, ? extends V> m) {
    this.loadFactor = DEFAULT_LOAD_FACTOR;
    putMapEntries(m, false);
}
final void putMapEntries(Map<? extends K, ? extends V> m, boolean evict) {
    int s = m.size();
    if (s > 0) {
        if (table == null) {
            float ft = ((float)s / loadFactor) + 1.0F;
            int t = ((ft < (float)MAXIMUM_CAPACITY) ?
                     (int)ft : MAXIMUM_CAPACITY);
            if (t > threshold)
                threshold = tableSizeFor(t);
        }
        else if (s > threshold) // 传入Map的size大于扩容容量,resize方法为重新初始化一下容量
            resize();
        for (Map.Entry<? extends K, ? extends V> e : m.entrySet()) {
            K key = e.getKey();
            V value = e.getValue();
            putVal(hash(key), key, value, false, evict);// 相当于put方法,请看下回分解
        }
    }
}

table:Node类型,做为空判断是否为新创建.
ft:是否要扩容的操作(为什么+1我现在只有个模糊的感觉,先留个坑)


发给官兵
47 声望23 粉丝

态度决定行为,行为决定习惯,习惯决定性格,性格决定命运