HashMap扩容大小为什么是2的幂
理想的状况,hashMap的存取就是O(1),也就是直接根据hashcode就可以找到它,每个bucket只存储一个节点,链表指向都是null,这样就比较开心了,不要出现一个链表很长的情况。
所以我们希望它能分布的均匀一点,如果让我们设计的话,我们肯定是直接对长度取模-----hashcode % length,但HashMap的设计者却不是这样写的,它写成了2进制运算,如下:
static final int hash(Object key) { int h; return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16); }
数组的具体存取规则是tab[(n-1) & hash],其中tab为node数组,n为数组的长度,hash为key的hash值。
为什么设计成(n - 1) & hash 这样呢?在 n 为 2次幂的情况下时,(n - 1) & hash ≈ hash % n ,因为2进制的运算速度远远高于取模,所以就使用了这种方式,所以要求为2的幂。
我们可以看到它求hash的过程,将32位的hashCode值向左移动16位,高位补0,也就是只要了高16位,这是为什么呢?因为hashcode的计算方法导致哈希值的差异主要在高位,而 (n - 1) & hash是忽略了容量以上的高位的,所以 使用h >>>16就是为了避免类似情况的哈希冲突。