栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

java1.8如何应对hash冲突的

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

java1.8如何应对hash冲突的

hashmap中put(K,V)方法,最终会执行putVal()方法,而在putVal()方法中会执行hash()方法;

public V put(K key, V value) {
        return putVal(hash(key), key, value, false, true);
}

static final int hash(Object key) {
    int h;
   // 判断key是否为null, 如果为null,则直接返回0;
   // 如果不为null,则返回(h = key.hashCode()) ^ (h >>> 16)的执行结果
    return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}

hash()方法把获取到的key的hashCode值再进行计算得到一个hash值,然后将(数组的长度-1)和hash值进行按位与操作:i = (n - 1) & hash得到元素在数组中存放的位置。
为什么不直接使用hashCode值与n-1进行按位与操作?
当n的长度比较小时,n-1的二进制高16位数全部都为0,只能利用低16位,会增加hash冲突的可能性,因为不同的hashCode值的二进制数的低16位数可能相同这样就会导致与n-1进行计算后的结果相同,导致存储的索引位置相同而发生hash冲突。

当我们使用进行 h ^ (h >>> 16) 操作时,会将h的高16位数据和低16位数据进行异或操作,最终得出的hash值的高16位保留了h值的高16位数据,而hash值的低16数据则是h值的高低16位数据共同作用的结果。所以即使h1和h2的低16位相同,最终计算出的hash值低16位也大概率是不同的,降低了hash冲突发生的概率。
这里面还有一个值的注意的点: 为什么是(n-1)?
HashMap的规定数组长度n为2的幂次方,那么n的二进制数的末尾一定为0与hash进行按位与操作最后一位就一定为0。这就导致元素存储索引位置都为偶数,使得数组中的奇数位为空,增加的hash冲突的可能性。
当使用n-1的时候得到一个奇数,二进制数的末尾就是1与hash进行按位与操作后最后一位可能为0也可能是1。充分利用了存储的数组的空间,降低了hash冲突。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/582922.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号