前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >细品Java8中hashCode方法

细品Java8中hashCode方法

作者头像
袁新栋-jeff.yuan
发布2020-12-02 15:04:58
5530
发布2020-12-02 15:04:58
举报

hashCode方法

简介

散列函数(英语:Hash function)又称散列算法、哈希函数,是一种从任何一种数据中创建小的数字“指纹”的方法。散列函数把消息或数据压缩成摘要,使得数据量变小,将数据的格式固定下来。

Java语言对hashCode的应用

3. 主要用途
  1. hashcode是Object中的函数,所有类都拥有的一个函数,主要返回每个对象的hash值,主要用于哈希表中,如HashMap、HashTable、HashSet。
  2. 在这里需要注意的是,他就是为了在一些对象数组里面存储的时候可以节省空间。(我在这里一直有个误会,就是hashCode 也会应用于对象的比较,主要比较的是对象的是否有被改变过,其实我们在进行比较的时候可以不进进行重写hashCode,单个的equals就可以保证这个对象是否相等。
  3. 但是很多面试官都会问到,你重写了equals 不重写hashcode 可以吗?不一定,当你重写的equals是那种两个对象所有值都相等的情况下的时候,我们就不需要重写。因为这样他就符合我们的正常逻辑,就是equals相等hashcode值一定相等。但是如果你的equals定义是只要这个对象中某个值相等就代表,这个对象相等,那么传统观念就被打破了。所以你就得按照你的equals来重写你的hashcode。保持一致。
4. Java 中hashcode存储的位置
  1. 存储在对象头markWord,如下图(深入理解Java虚拟机)
在这里插入图片描述
在这里插入图片描述
  1. 我们知道了他是存储的位置,那他是什么时候存储进去的呢? 在Java中所有的对象都是有hashcode吗?
5. Java中HashCode的实现
  1. 在Java中Object.class中有hashCode方法,方法是native 方法,实现就是在JVM中实现的,也就是说他是使用C语言实现的。
  2. 实现方式:OpenJDK8 默认hashCode的计算方法是通过和当前线程有关的一个随机数+三个确定值,运用Marsaglia’s xorshift scheme随机数算法得到的一个随机数。和对象内存地址无关。三个确定确定值分别是:
代码语言:javascript
复制
// thread-specific hashCode stream generator state - Marsaglia shift-xor form
    //随机数
  _hashStateX = os::random() ;
    //确定值1
  _hashStateY = 842502087 ;
      //确定值2
  _hashStateZ = 0x8767 ;    // (int)(3579807591LL & 0xffff) 
      //确定值3
  _hashStateW = 273326509 ;
  1. 可以通过在JVM启动参数中添加-XX:hashCode=4,改变默认的hashCode计算方式。
6. 为什么要重写hashCode
  1. 如上文提到,我们不按传统规则重写了equals方法,所以为了不违反规则也就得重写hashCode。 2.源码中hashcode的重写,如hashMap中
  • 如果m1.entrySet( ).equals(m2.entrySet()),则两个映射m1和 m2表示相同的映射 。这样可确保 equals方法可在Map接口的不同实现中正常工作。
代码语言:javascript
复制
    static <K, V> boolean equals(Map<K, V> source, Object object) {
        if (source == object) {
            return true;
        } else if (source != null && object instanceof Map) {
            final Map<K, V> map = (Map<K, V>) object;
            if (source.size() != map.size()) {
                return false;
            } else {
                try {
                    return source.forAll(map::contains);
                } catch (ClassCastException e) {
                    return false;
                }
            }
        } else {
            return false;
        }
    }
  • 映射的哈希码定义为映射的entrySet()视图中每个条目的哈希码之和 。这确保了m1.equals(m2) 隐含了对任何两个映射 m1和m2的m1.hashCode()== m2.hashCode(),这是的总合同要求的 。Object.hashCode()
代码语言:javascript
复制
、、
    @Override
    public int hashCode() {
        return Collections.hashUnordered(this);
    }
    
        // hashes the elements regardless of their order
    static int hashUnordered(Iterable<?> iterable) {
        return hash(iterable, (acc, hash) -> acc + hash);
    }
  • 注意点 hashMap重写hashCode 和 计算hash桶位置的是不同的,这两个可不敢弄混了,我是弄混了。 下来我们再看看hash桶下表的计算。jdk 1.8中的。
代码语言:javascript
复制
/**
/ ** *计算key.hashCode()并将(XOR)散列的较高位*扩展到较低位。
    * 因为该表使用2的幂次掩码,所以*仅在当前掩码上方的位中发生变化的*哈希集将**总是发生冲突。 (众所周知的示例是Float键集*在小表中保存连续的整数。)
    *因此,我们*应用了一种变换,向下扩展了较高位的影响。在速度,效用和比特扩展*质量之间需要权衡。由于许多常见的哈希集*已经合理地分布了(因此不能从*扩展*中受益),并且由于我们使用树来处理bin中的大量*冲突集,因此我们仅以*最便宜&的方式对一些移位后的位进行XOR运算,减少系统损失,以及*合并最高位的影响,否则由于表的限制,这些位将永远不会在索引计算中使用
    * /
    static final int hash(Object key) {
        int h;
        return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
    }

总结

  1. hashCode的简介
  2. Java 中 Object.hashCode()的实现
  3. 为什么要重写hashCode()?不打破传统规则
  4. HashMap中hashCode方法的重写。
  5. HashMap中hash桶的hash计算。

参考

https://docs.oracle.com/javase/8/docs/api/java/util/Map.html#hashCode() https://docs.oracle.com/javase/8/docs/api/java/util/Map.html#equals(java.lang.Object) https://juejin.cn/post/6844903487432556551

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020-11-30 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • hashCode方法
    • 简介
      • Java语言对hashCode的应用
        • 3. 主要用途
        • 4. Java 中hashcode存储的位置
        • 5. Java中HashCode的实现:
        • 6. 为什么要重写hashCode
    • 总结
    • 参考
    相关产品与服务
    对象存储
    对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档