美文网首页Android
ConcurrentHashMap设置初始容量底层现象

ConcurrentHashMap设置初始容量底层现象

作者: Karl90 | 来源:发表于2020-01-01 23:51 被阅读0次

问题:

我们在创建ConcurrentHashMap对象的时候通常直接new ConcurrentHashMap();,此时底层默认初始容量为16。那么如果手动设置初始容量new ConcurrentHashMap(int initialCapacity);会发生什么呢?请看下面分析:

几个用到的变量值转换:

@Native public static final int   MAX_VALUE = 0x7fffffff = 2^31 - 1
static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8 = 2^31 - 1 - 2^3 = 2 ^ 28 - 1
//32位hash 最高2位勇于控制
private static final int MAXIMUM_CAPACITY = 1 << 30 = 1 << 30 =  2 ^ 0 << 30 = 2 ^ 30

底层方法实现:

//初始化时设置初始容量
//设置initialCapacity = 9      (2 ^ 3 + 1)
public ConcurrentHashMap(int initialCapacity) {
        if (initialCapacity < 0)
            throw new IllegalArgumentException();
            //32位hash 最高2位勇于控制
            //MAXIMUM_CAPACITY = 1 << 30 =  2 ^ 0 << 30 = 2 ^ 30
            //如果大于则cap = 2 ^ 31
        int cap = ((initialCapacity >= (MAXIMUM_CAPACITY >>> 1)) ?
                   MAXIMUM_CAPACITY :
                   tableSizeFor(initialCapacity + (initialCapacity >>> 1) + 1));    // 14
        this.sizeCtl = cap;
}


//c = 14
private static final int tableSizeFor(int c) {
        int n = c - 1;                      //n = 13
        n |= n >>> 1;                   //n = 13 | 6 = 1101 | 0110 = 1111 = 15
        n |= n >>> 2;                   //n = 15 | 3 = 1111 | 0011 = 1111 = 15
        n |= n >>> 4;                   //n = 15 | 0 = 1111 | 0000 = 1111 = 15
        n |= n >>> 8;                   //n = 15
        n |= n >>> 16;                  //n = 15
        return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;  //返回16
}

测试几个值:

//1. 测试设置initialCapacity = 7
tableSizeFor(11);
int n = 11 - 1 = 10
n = 10 | 10 >>> 1 = 1010 | 0101 = 1111 = 15
n = 15 | 15 >>> 2 = 1111 | 0011 = 1111 = 15
n = 15
return 15 + 1 = 16;

//2. 测试设置initialCapacity = 17
tableSizeFor(26);
int n = 26 - 1 = 25
n = 25 | 25 >>> 1 = 11001 | 01100 = 11101 = 29
n = 29 | 29 >>> 2 = 11001 | 00111 = 11111 = 31
n = 31
return 31 + 1 = 32;

//3. 测试设置initialCapacity = 3
tableSizeFor(5);
n = 5 | 5 >>> 1 = 0101 | 0010 = 0111 = 7
n = 7 | 7 >>> 2 = 0111 | 0001 = 0111 = 7
n = 7
return 7 + 1 = 8;

//4. 测试设置initialCapacity = 2
tableSizeFor(4)
int n = 4 - 1 = 3
n = 3 | 3 >>> 1 = 11 | 01 = 11 = 3
n = 3
return 3 + 1 = 4

//5. 测试设置initialCapacity = 4
tableSizeFor(7)
int n = 7 - 1 = 6
n = 6 | 6 >>> 1 = 110 | 011 = 111 = 7
n = 3
return 7 + 1 = 8

//6. 测试设置initalCapacity = 8
tableSizeFor(13)
int n = 13 - 1 = 12
n = 12 | 12 >>> 1 = 1100 | 0110 = 1110 = 14
n = 14 | 14 >>> 1 = 1110 | 0111 = 1111 = 15
n = 15
return 15 + 1 = 16

产生的现象:

//2 --> 4
//3 --> 8                           特殊现象:3 * 2 = 6距离4和8相等,选择向后转换为8
//4 --> 8
//7 --> 16
//8 --> 16
//9 --> 16
//17 --> 32

结论:

ConcurrentHashMap初始化设置容量时底层会自动转换为距设置值2倍最近的2的次幂;当前后距离相等时,会选择向后转换。

相关文章

网友评论

    本文标题:ConcurrentHashMap设置初始容量底层现象

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