跳至主要內容

构造方法

mozzie大约 2 分钟JavaJava

构造方法

  • 无参构造, 散列表结构延迟初始化,默认的数组大小是 16:
public ConcurrentHashMap() {
}
  • 有参构造:
public ConcurrentHashMap(int initialCapacity) {
    // 指定容量初始化
    if (initialCapacity < 0) throw new IllegalArgumentException();
    int cap = ((initialCapacity >= (MAXIMUM_CAPACITY >>> 1)) ?
               MAXIMUM_CAPACITY :
               // 假如传入的参数是 16,16 + 8 + 1 ,最后得到 32
               // 传入 12, 12 + 6 + 1 = 19,最后得到 32,尽可能的大,与 HashMap不一样
               tableSizeFor(initialCapacity + (initialCapacity >>> 1) + 1));
    // sizeCtl > 0,当目前 table 未初始化时,sizeCtl 表示初始化容量
    this.sizeCtl = cap;
}
private static final int tableSizeFor(int c) {
    int n = c - 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;
}

HashMap 部分详解了该函数,核心思想就是把最高位是 1 的位以及右边的位全部置 1,结果加 1 后就是 2 的 n 次幂

  • 多个参数构造方法:
public ConcurrentHashMap(int initialCapacity, float loadFactor, int concurrencyLevel) {
    if (!(loadFactor > 0.0f) || initialCapacity < 0 || concurrencyLevel <= 0)
        throw new IllegalArgumentException();
    // 初始容量小于并发级别
    if (initialCapacity < concurrencyLevel)  
        // 把并发级别赋值给初始容量
        initialCapacity = concurrencyLevel; 
	// loadFactor 默认是 0.75
    long size = (long)(1.0 + (long)initialCapacity / loadFactor);
    int cap = (size >= (long)MAXIMUM_CAPACITY) ?
        MAXIMUM_CAPACITY : tableSizeFor((int)size);
    // sizeCtl > 0,当目前 table 未初始化时,sizeCtl 表示初始化容量
    this.sizeCtl = cap;
}
  • 集合构造方法:
public ConcurrentHashMap(Map<? extends K, ? extends V\> m) {
    this.sizeCtl = DEFAULT_CAPACITY;	// 默认16
    putAll(m);
}
public void putAll(Map<? extends K, ? extends V\> m) {
    // 尝试触发扩容
    tryPresize(m.size());
    for (Entry<? extends K, ? extends V\> e : m.entrySet())
        putVal(e.getKey(), e.getValue(), false);
}
private final void tryPresize(int size) {
    // 扩容为大于 2 倍的最小的 2 的 n 次幂
    int c = (size >= (MAXIMUM_CAPACITY >>> 1)) ? MAXIMUM_CAPACITY :
    	tableSizeFor(size + (size >>> 1) + 1);
    int sc;
    while ((sc = sizeCtl) >= 0) {
        Node\<K,V\>[] tab = table; int n;
        // 数组还未初始化,【一般是调用集合构造方法才会成立,put 后调用该方法都是不成立的】
        if (tab == null || (n = tab.length) == 0) {
            n = (sc > c) ? sc : c;
            if (U.compareAndSwapInt(this, SIZECTL, sc, -1)) {
                try {
                    if (table == tab) {
                        Node\<K,V\>[] nt = (Node\<K,V\>[])new Node<?,?>[n];
                        table = nt;
                        sc = n - (n >>> 2);// 扩容阈值:n - 1/4 n
                    }
                } finally {
                    sizeCtl = sc;	// 扩容阈值赋值给sizeCtl
                }
            }
        }
        // 未达到扩容阈值或者数组长度已经大于最大长度
        else if (c <= sc || n >= MAXIMUM_CAPACITY)
            break;
        // 与 addCount 逻辑相同
        else if (tab == table) {
           
        }
    }
}
贡献者: mozzie