结论:
1 提高计算效率;
2 增大Hash扰动,减少Hash碰撞
一、提高计算效率
假设HashMap的长度是16。index1的计算是Java8之后获取索的位置。&运算比取余运算效率更高。但是二者结果又一致。
public static void main(String[] args) {
int size = 16;
String key = "gosaint";
int h = key.hashCode();
int hash = h ^ (h >>> 16);
int index1 = hash & (size - 1);
int index2 = hash % (size);
System.out.println(hash);//210636407
System.out.println(index1);//7
System.out.println(index2);//7
}
二、增大Hash扰动,减少Hash碰撞
假设现在数组的长度 length 可能是偶数也可能是奇数length 为偶数时,length-1 为奇数,奇数的二进制最后一位是 1,这样便保证了 hash &(length-1) 的最后一位可能为 0,也可能为 1(这取决于 h 的值),即 & 运算后的结果可能为偶数,也可能为奇数,这样便可以保证散列的均匀性。
假如length=16。length-1=15。hash=210636407.(奇数)
1100 1000 1110 00001110 01110111
0000 0000 0000 00000000 00001111
-------------------------------------------------
0000 00000000 00000000 00000111
计算的最终结果是7. 假设hash=210636408.(偶数) 。最终是8.
而如果 length 为奇数的话,很明显 length-1 为偶数,它的最后一位是 0,这样 hash & (length-1) 的最后一位肯定为 0,即只能为偶数,这样任何 hash 值都只会被散列到数组的偶数下标位置上,这便浪费了近一半的空间