java中Map.hashCode()函数说明

在java中,Map.hashCode()函数是在具有一定工作积累后,为了更好的成长不可避免需要研究的内容。

首先,我们先看下原始代码:

    static final int hash(Object key) {
        int h;
        return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
    }
  public native int hashCode();

一、hashCode()函数

我们可以看到hashCode()函数是一个 native标记的函数,因此我们目前只可以对照上方的注释来对该函数进行一定的说明。

总结如下:

  1. 该方法会返回一组hash值,目的是更好的满足诸如HashMap散列图表所需的散列算法值(并不是说对于普通对象没有用);
  2. 在程序执行时,在不改变现有对象及内部的情况下保证每次执行获得一个相同的integer值(注意,是一个int值,32位);但不保证在两次执行时,相同情况创建的对象code相等;
  3. 在equals()函数相等的两个对象,他们的hashCode值一直相等;
  4. 在equals()函数不相等的两个对象,他们的hashCode值不一定一直相等(可以理解为:为了保证不同对象hashCode必定不相等,并不是明智的,必定会损耗一定的系统资源和效率);
  5. 对于一个特定的对象他的hashCode值差不多是特别的(可以理解为通过转换对象在内存中的地址获取到的hashCode,并且这个值得获取不需要java技术实现(因此是native));

如果不太清楚,请多阅读几遍这些总结,对hashCode()函数来说,这些也真的是他的核心了。

二、hash(Object key)函数

对与hash()函数,相对会简单理解很多。

总结如下:

  1. (h = key.hashCode()) ^ (h >>> 16) 对这行代码理解为:为了使hash后的值更加的散列,使高16位bit(int的长度是32位)和低16位bit进行,异或运算,使低16位同时具有高位和低位的特点,这样的目的是,在极端情况下,高位可能并不参与任何的哈希计算(比如在一个小的table中 使用连续的float数值作为key,在计算时,碰撞是经常发生的。如果只使用hashCode作为hash,对于高位来说,起到的作用也是有限的);
  2. 要明白之所以使用这样的方式计算,也是从速度,效率,实用性这些综合考量的结果;使用简单的异或计算可以减少系统的损耗

三、补充

引用链接:HashMap中hash值的计算 - 知乎

虽然HashMap使用拉链法作为hash碰撞的解决方案,但是仍可以在hash函数的设置上去进行一定程度的优化,来减少碰撞的可能性。

  • 如果直接使用key.hashCode()作为hash值的话,存在一些问题。
    举例说明,HashMap的默认长度为16,并且是通过(table.length - 1) & hash的方式得到key在table中的下标
    如果key1.hashCode()=1661580827(二进制为0110,0011,0000,1001,1011,0110,0001,1011),key2.hashCode()=1661711899(二进制为0110,0011,0000,1011,1011,0110,0001,1011)
    在与掩码进行与的过程中,只有后4位起作用,导致得到的下标值均为11,导致高位完全失效,加大了冲突的可能性。
  • 如果通过高位向低位异或传播的话,高位同样参与到key在table中下标的运算,减少了碰撞的可能性
    key1.hashCode() ^ (key1.hashCode() >>>16)=1661588754(二进制为0110,0011,0000,1001,1101,0101,0001,0010)
    key2.hashCode() ^ (key2.hashCode() >>>16)=1661719824(二进制为0110,0011,0000,1011,1101,0101,0001,0000)
    在于掩码进行与操作得到的下标分别为2和0,减少了冲突的可能性。

(文章如存在任何问题,欢迎指正,共同进步)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值