我的理解 作下记录,不正确的地方望不吝赐教node
这是hashmap初始化容量时候 对容量大小作的处理,保证初始化容量为最近的2的幂次方(JDK1.8)数组
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.奇数不行的解释很能被接受,在计算hash的时候,肯定落在数组的位置的时候,计算方法是(n - 1) & hash ,奇数n-1为偶数,偶数2进制的结尾都是0,通过&运算末尾都是0,会增长hash冲突。 2.为啥要是2的幂,不能是2的倍数么,好比6,10? 2.1 hashmap 结构是数组,每一个数组里面的结构是node(链表或红黑树),正常状况下,若是你想放数据到不一样的位置,确定会想到取余数肯定放在那个数据里, 计算公式: hash % n,这个是十进制计算。在计算机中, (n - 1) & hash,当n为2次幂时,会知足一个公式:(n - 1) & hash = hash % n,计算更加高效。 2.2 只有是2的幂数的数字通过n-1以后,二进制确定是 ...11111111 这样的格式,这种格式计算的位置的时候,彻底是由产生的hash值类决定,而不受n-1 影响。你可能会想,受影响不是更 好么,又计算了一下 ,hash冲突可能更低了,这里要考虑到扩容了,2的幂次方*2,在二进制中好比4和8,表明2的2次方和3次方,他们的2进制结构类似 0000 0100 0000 1000 只是高位向前移了一位,这样扩容的时候,只须要判断高位hash,移动到以前位置的倍数就能够了,免去了从新计算位置的运算。