Java中,HashMap是我们经常使用到的集合,其底层数据结构是数组+链表+红黑树。当向一个map添加元素时map.put("a","b"),有以下几个过程:
- 计算key的hashCode值
- 将key的hashCode值高低16位异或得出codeValue
- 将codeValue和map容量长度-1相与得出数组索引
- 最后将value放到指定索引位置
其实很多人都很疑惑,为什么需要将key的hashCode的高低位异或?也许有人知道是为了防止hash冲突,但是怎么就能防止冲突呢?
我们举个简单的例子,下面定义一个map,容量是16
Map myMap = new HasMap(16);
假设我们不将key的hashCode值高低位异或,有两个key分别为key1和key2,对应的hashCode如下
可以看出这两个hashCode的低16位都是相同的,但是高16位不相同。再计算数组的索引时,对应的结果如下
可以看出虽然两个可以的hashCode的高位不同,但是最终得出的数组索引位置却是相等的,这就导致了冲突。所以为了降低发生的概率,jdk对hashCode做了优化,将key的hashCode的高低16位异或之后,再计算数组索引。因为key的高位不同,得出的异或值也不相同,最终计算出的数组索引也不同,降低了hash冲突的概率。
key1的hashCode高低位异或后计算的数组索引:
key2的hashCode高低位异或后计算的数组索引:
可以得出,key1和key2经过高低位异或的处理,最终计算出来的数组索引是不相同的,降低了hash冲突的概率。
#Java#