分析
- HashMap在扩容时会把 Node 桶中的元素拆分成两个链表或者红黑树 (分别对应桶为链表或红黑树), - JDK1.8 扩容流程,然后根据位运算来判断 Node 桶中的结点插入两个中的哪一个。(下文中会用 low,high表示)
- 扩容时执行的 resize( ) 方法中的源码,把当前结点插入到 low 还是 high 的判断条件是 (e.hash & oldCap) == 0,那到底这个 & 运算的意义何在呢?
- 首先我们知道 HashMap 计算 key 所对应数组下标的公式是 (length - 1) & hash,其中 length 是数组长度,hash 是 hash值,这个公式等价于 hash % length (当 length 是 2 的 n 次幂时) 。
- 从下图中我们可以看出,hash % length 的结果只取决于小于数组长度的部分,这个 key 的 hash 值的低四位就是当前所在数组的下标。扩容后 新数组长度 = 旧数组长度 * 2,也就是左移 1 位,而此时 hash % length 的结果只取决于 hash 值的低五位,前后两者之间的差别就差在了第五位上。
- 如果第五位是 0,那么只