关于HashMap的扩容机制和及其算法的一些思考
一、前言
本文为HashMap源码记录篇幅之一,引用了部分基础知识的URL,侵删
mail:dustfree2018@gmail.com
二 、基础
1 位运算
-
"<<<" :无符号左移动三位,
8-> 0000 1000 左移动三位 0100 0000=2^6= 32
-
">>>": 无符号右移动三位
8-> 0000 1000 右移动三位 0000 0001 =2^0=1
-
"|=" : 或等于
有1则为1 ,反之为0。
例: 0000 1000
右移三位得 0000 0001
= 0000 1001=9
三 解析
/**
* The maximum capacity, used if a higher value is implicitly specified
* by either of the constructors with arguments.
最大容量,如果隐式指定更高的值,则使用该容量
* MUST be a power of two <= 1<<30.
* 必须是两个<= 1 << 30的幂。
*/
static final int MAXIMUM_CAPACITY = 1 << 30;
static int tableSizeFor(int cap) {
int n = cap - 1;
//>>>二进制无符号右移
//|= n 的二进制 有1则为1, 否则为0
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;
}
四 情况
-
cap<=0000 0100 假设为4,减1后为 0000 0011
n |= n >>> 1;- 3>>1=0000 0001=1
- 3|=1 ->0000 0011|=0000 0001=0000 0011=3
右移大于1位时,则右移后的数字为0。与原值进行|= 运算无意义,因此不做详解。
结论,等于cap<=4即cap<=0000 0100 cap不做变更,为原值。
-
cap>=0000 0100 假设cap=35 减1后为34 -> 0010 0010
n |= n >>> 1;
- n=cap-1=34
- n -> 0010 0010
- n>>>1= 0001 0001
- 0010 0010 |= 0001 0001 得出 0011 0011 ->32+16+2+1=41=n
n |= n >>> 2;
- 0011 0011>>>2 -> 0000 1100
- 0011 0011 |= 0000 1100=0011 1111
- n= 63
n |= n >>> 4;
- 0011 1111 >>>4 得到 0000 1111
- 0011 1111 |= 0000 1111 得到 0011 1111
- n=63
………………
右移大于8位,右移后的数值为0 ,进行|= 运算为左侧(n)值,此时无意义,更大数字可以进行尝试,结论一致。
(n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
n+1=64
五 结论
-
等于cap<=4即cap<=0000 0100 cap不做变更,为原值。
-
cap大于等于4 二进制为0000 0100 ,向上取值,其二进制数最终结果为其去除补位0后,最高位为1的位置为起始点,后续数值转换为1。比如:传入cap=5 n=cap-1=4->0100 右移一位得 0010 |= 0110 然后
-
- n=cap-1=4 0100
- n>>>1. 0010
- n|=0010 0110
- n>>>2 0001
- n|=0001 0111
- 得出结果,7
- cap=n+1=8