初探HashMap之构造方法

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

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

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会用到此方法)java

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.75fthis

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我如今只有个模糊的感受,先留个坑)code

相关文章
相关标签/搜索