JAVA知识点-HashMap高低16位异或的原因

本文最后更新于:July 6, 2022 pm

积土成山,风雨兴焉;积水成渊,蛟龙生焉;积善成德,而神明自得,圣心备焉。故不积跬步,无以至千里,不积小流无以成江海。齐骥一跃,不能十步,驽马十驾,功不在舍。面对悬崖峭壁,一百年也看不出一条裂缝来,但用斧凿,能进一寸进一寸,能进一尺进一尺,不断积累,飞跃必来,突破随之。

目录

原因

主要原因是保留高16位与低16位的特性,增大散列程度。

分析

我们知道,哈希散列时的范围和HashMap的大小是有关系的。具体可见 《JAVA集合源码-HashMap的长度为2的幂次方的原理 》

所以,当数组的长度很短时,只有低位数参与了运算,而高位并没参与运算。而高位不同,低位相同的数有很多,这样最后算出来的索引就会是一样的。例如:

hashCode为 11 1111 0001,那么11 1111 0001 & 1111 = 0001,高位发生变化时10 1111 0001 & 1111 = 000110 0111 0001 & 1111 = 0001,也就是说在高位发生变化时,最后算出来的索引都是一样的,这样就会导致很多数据都被放到一个数组里面了,造成性能退化。

HashMap将高16位与低16位进行异或,这样可以保证高位的数据也参与到运算中来,以增大索引的散列程度,让数据分布得更为均匀 。

而至于为什么用异或进行运算,而不是 & 和 | ,主要原因为:异或运算能更好的保留各部分的特征,如果采用&运算计算出来的值会向0靠拢(有0就为0),采用 | 运算计算出来的值会向1靠拢(有1就为1)。