hashMap源码算法问题

在读HashMap源码的时候,有些位运算的目的和原理不是很清楚,特地记下来以便日后复习使用。
1 为什么hashMap内hash方法会对原对象hash值右移16位?
`static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);//这里对key,hash值右移了16位
}`
hash值位int类型,长度位32bit,右移16位后再与自身的hash值进行与操作,会提高hash值计算方法的复杂度,提高hashMap中hash值的散列程度,使其更均匀的分布。
2 扩容拆分链表时为什么是hash值与原有数组的大小进行并操作(存放下标是等于对象hash值与现有数组长度减一进行取余的操作)?
`if ((e.hash & oldCap) == 0) {
if (loTail == null)
loHead = e;
else loTail.next = e;
loTail = e;
}`
此操作是为了确定链表的节点元素在新数组中的下标位置,若等于0则位置不变,如果不为0,则位置位现在所处的位置下标+原有数组长度,下面来分析一下原理。
首先来明确一个概念,hashmap中元素的存放位置与数组下标的关系是:

数组下标=元素的hash值&(数组长度-1)
而且hashmap的长度一定是2的n次方。
那么原有数组长度的二进制数可以这样表示 1 0 0 0 0
扩容后数组长度为                   1 0 0 0 0 0
原有数组长度减一后为                 0 1 1 1 1
现有数组长度减一后为               0 1 1 1 1 1
那么原有数组中元素存放位置下标只与后四位有关,扩容后只与后五位有关,那么,如果只与第五位进行与操作的话,就可以判断出该元素存放位置是否需要改变了。

你可能感兴趣的:(java)