数组里面相同key值_HashMap中key的hashCode为何异或处理?

Java中,HashMap是我们经常使用到的集合,其底层数据结构是数组+链表+红黑树。当向一个map添加元素时map.put("a","b"),有以下几个过程:

  1. 计算key的hashCode值
  2. 将key的hashCode值高低16位异或得出codeValue
  3. 将codeValue和map容量长度-1相与得出数组索引
  4. 最后将value放到指定索引位置

其实很多人都很疑惑,为什么需要将key的hashCode的高低位异或?也许有人知道是为了防止hash冲突,但是怎么就能防止冲突呢?

我们举个简单的例子,下面定义一个map,容量是16

Map myMap = new HasMap(16);

假设我们不将key的hashCode值高低位异或,有两个key分别为key1和key2,对应的hashCode如下

622e9e6ffe06d487f0c81ffb64296a78.png

hashcode

可以看出这两个hashCode的低16位都是相同的,但是高16位不相同。再计算数组的索引时,对应的结果如下

dae2bff5ef0aea9e6d4d0073fde1cc55.png

key1:hashcode&(16-1)

988e643ca8f2b7930bfd32a5dbf7fa6e.png

key2:hashcode&(16-1)

可以看出虽然两个可以的hashCode的高位不同,但是最终得出的数组索引位置却是相等的,这就导致了冲突。所以为了降低发生的概率,jdk对hashCode做了优化,将key的hashCode的高低16位异或之后,再计算数组索引。因为key的高位不同,得出的异或值也不相同,最终计算出的数组索引也不同,降低了hash冲突的概率。

key1的hashCode高低位异或后计算的数组索引:

12662aed6ba6f51e78da9fd289054d1b.png

key2的hashCode高低位异或后计算的数组索引:

79a7ef6919d6482f645d929919239986.png

可以得出,key1和key2经过高低位异或的处理,最终计算出来的数组索引是不相同的,降低了hash冲突的概率。

#Java#

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Java,每个对象都有一个hashCode()方法,用于计算对象的哈希。当我们调用一个对象hashCode()方法时,它根据对象的内容计算出一个哈希,哈希是一个int类型的整数。 在HashMap,当我们需要将一个键对存储到哈希表时,需要先计算出键的哈希HashMap使用以下公式计算键的哈希: ``` h = key.hashCode() ^ (key.hashCode() >>> 16); ``` 其,^表示按位异或运算符,>>>表示无符号右移运算符。 这个公式的作用是将hashCode()方法返回的32位哈希进行扰动,以减少哈希冲突的概率。具体来说,这个公式将哈希的高16位与低16位进行异或运算,然后将结果右移16位,得到一个新的哈希。 在JavahashCode()方法的实现可能因为不同的JVM和不同的版本而有所不同,因此,我们在使用HashMap时,应该遵循以下原则: 1. 对于同一个对象,多次调用其hashCode()方法应该返回相同。 2. 如果两个对象equals()方法返回true,则它们的hashCode()方法应该返回相同。 3. 如果两个对象equals()方法返回false,则它们的hashCode()方法不一定返回不同的,但是不同的哈希可以降低哈希冲突的概率。 在实际使用,为了减少哈希冲突的概率,我们可以通过重写对象hashCode()方法来实现自己的哈希函数。在重写hashCode()方法时,我们应该尽量保证哈希的唯一性和随机性,以提高哈希表的性能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值