源码
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;
}
分析
static final int tableSizeFor(int cap) {
int n = cap - 1;
n |= n >>> 1;
System.out.println(Integer.toBinaryString(n));
n |= n >>> 2;
System.out.println(Integer.toBinaryString(n));
n |= n >>> 4;
System.out.println(Integer.toBinaryString(n));
n |= n >>> 8;
System.out.println(Integer.toBinaryString(n));
n |= n >>> 16;
System.out.println(Integer.toBinaryString(n));
return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
}
测试类
public static void main(String[] args) {
int a = 65538;
System.out.println(Integer.toBinaryString(a));
int i = tableSizeFor(a);
System.out.println(i);
}
运行结果
10000000000000010
11000000000000001
11110000000000001
11111111000000001
11111111111111111
11111111111111111
结果分析
第一次运行:
10000000000000010 n >>> 1;
01000000000000000 进行|运算
11000000000000001
分析:
把最大位的1,通过位移后移一位,并且通过|运算,组合起来
第二次运行:
11000000000000001 n >>> 2;
00110000000000000 进行|运算
11110000000000001
分析:
把最大的两位,已经变成1的,往后移动两位,并且通过|运算,组合起来
第三次运行:
11110000000000001 n >>> 4;
00001111000000000 进行|运算
11111111000000001
分析:
把最大4位,已经变成1的,往后移动4位,并且通过|运算,组合起来
第四次运行:
11111111000000001 n >>> 8;
00000000111111110 进行|运算
11111111111111111
分析:
把最大的8位,已经变成1的,往后移动8位,并且通过|运算,组合起来
第五次运算:
同上。因为我的数据,最大只到17位,所有第五次没有效果。可以用32位来进行运算,
第五次是通过前16位已经变成1的数据,往后移动16位,然后通过|运算,最后的结果是32位都变成1。
第六次运算:
hashMap的长度为2的N次方
所有最后的数据格式为1后面N个0的格式
所有最后一步N+1
总结
前面的操作是保证参数的二进制位都是1,转为十进制是个奇数,+1变为偶数,这个偶数一定是2的N次方, 此时为hashMap初始容量2的N次方,后面在容器中添加数据,如果达到了2的N次方的0.75,还会触发容器 扩容,所以制定容器大小最好为new HashMap(1000/0.75);这样容器存储你想存的1000个元素不会触发扩容。
本文为参考写出,如有侵权,请联系我第一时间删除