为什么 HashMap 的容量是 2 的倍数呢?
HashMap 的容量是 2 的倍数,或者说是 2 的整数次幂,是为了快速定位元素的下标: HashMap 在定位元素位置时,先通过 hash(key) = (h = key.hashCode()) ^ (h >>> 16) 计算出哈希值,再通过 hash & (n-1) 来定位元素位置的,n 为数组的大小,也就是 HashMap 的容量。 因为(数组长度-1)正好相当于一个“低位掩码”——这个掩码的低位最好全是 1,这样 & 操作才有意义,否则结果就肯定是 0。 a&b 操作的结果是:a、b 中对应位同时为 1,则对应结果位为 1,否则为 0。例如 5&3=1,5 的二进制是 0101,3 的二进制是 0011,5&3=0001=1。 2 的整次幂(或者叫 2 的整数倍)刚好是偶数,偶数-1 是奇数,奇数的二进制最后一位是 1,保证了 hash &(length-1) 的最后一位可能为 0,也可能为 1(取决于 hash 的值),即 & 运算后的结果可能为偶数,也可能为奇数,这样便可以保证哈希值的均匀分布。 换句话说,& 操作的结果就是将哈希值的高位全部归零,只保留低位值。 假设某哈希值的二进制为 10100101 11000100 00100101,用它来做 & 运算,我们来看一下结果。 我们知道,HashMap 的初始长度为 16,16-1=15,二进制是 00000000 00000000 00001111(高位用 0 来补齐):
10100101 11000100 00100101& 00000000 00000000 00001111---------------------------------- 00000000 00000000 00000101因为 15 的高位全部是 0,所以 & 运算后的高位结果肯定也是 0,只剩下 4 个低位 0101,也就是十进制的 5。 这样,哈希值为 10100101 11000100 00100101 的键就会放在数组的第 5 个位置上。