java对象hashCode存在的必要性是什么?

加快判断两个对象是否相等

为什么是“加快”判断呢?接下来我们好好履履什么是hashCode,还有hashCode的作用场景,只要清晰的认识到hashCode的整个逻辑,什么八股“hashCode跟equals”这种问题再也不会难倒了。

1、hashCode是什么?

1.1、从源码看起

    /**
     * Returns a hash code value for the object. This method is
     * supported for the benefit of hash tables such as those provided by
     * {@link java.util.HashMap}.
     * <p>
     * The general contract of {@code hashCode} is:
     * <ul>
     * <li>Whenever it is invoked on the same object more than once during
     *     an execution of a Java application, the {@code hashCode} method
     *     must consistently return the same integer, provided no information
     *     used in {@code equals} comparisons on the object is modified.
     *     This integer need not remain consistent from one execution of an
     *     application to another execution of the same application.
     * <li>If two objects are equal according to the {@code equals(Object)}
     *     method, then calling the {@code hashCode} method on each of
     *     the two objects must produce the same integer result.
     * <li>It is <em>not</em> required that if two objects are unequal
     *     according to the {@link java.lang.Object#equals(java.lang.Object)}
     *     method, then calling the {@code hashCode} method on each of the
     *     two objects must produce distinct integer results.  However, the
     *     programmer should be aware that producing distinct integer results
     *     for unequal objects may improve the performance of hash tables.
     * </ul>
     * <p>
     * As much as is reasonably practical, the hashCode method defined by
     * class {@code Object} does return distinct integers for distinct
     * objects. (This is typically implemented by converting the internal
     * address of the object into an integer, but this implementation
     * technique is not required by the
     * Java&trade; programming language.)
     *
     * @return  a hash code value for this object.
     * @see     java.lang.Object#equals(java.lang.Object)
     * @see     java.lang.System#identityHashCode
     */
    public native int hashCode();

我简单的翻译一下,主要有这么几个点:

  • 返回一个对象的hash码,可以为hash表这样的hash数据结构提供便利
  • 在一个Java进程内,一个对象的hashCode 始终是相等的
  • 硬性要求,如果通过equals比较两个对象是否相等时,那么一定要保证相等的两个对象的hashCode也是相等的
  • 它不是必需的,如果按照equals(java.lang.Object)法两个对象是不平等的,然后调用hashCode方法每一个对象必须产生不同的整数结果。然而,程序员应该意识到,产生不同的整数结果的不平等的对象可能会提高哈希表的性能。
  • 这个hashCode是由内存地址计算得到的。

我们可以得到结论就是,判断两个对象是否相等在Java中根本跟hashCode没半毛线关系,用的是equals方法判断两个对象是否相等。但是有些对象equals会消耗比较多的性能,比如String对象需要对每个字符做比较,所以利用了hashCode先做一次预判断(O(1)),当hashCode相等的时候再使用equals再做判断。关于这个点,可以从我们熟悉的HashMap里面得到答案。每次判断key相等时候都会想比较hash(这个值是从hashCode计算出来的),然后再==,然后再equals。这个过程已经可以筛选掉一大波不击中的key了。

            if (p.hash == hash && ((k = p.key) == key || (key != null && key.equals(k))))

为什么hashCode为什么就能确定两个对象不一样?这个方法是native的,在网上找了一张图,我们通过这张图,来了解到它的计算方式

1.2、hashCode的生成机制

参考:https://blog.caoxudong.info/blog/2013/12/12/default_hashcode_implmentation_in_hotspot

在这里插入图片描述
得到的结论就是:hashCode会被记录到对象头里面,生成方式是根据对象地址来做移位跟与操作得到的。所以就有了下面的问题,也是之前的一篇文章提到过的。

1.3、hashCode与==的关系

==:这个符号是判断两个对象的内存地址是否一致
hashCode:是通过内存地址计算出来的
所以,我们在不覆盖hashCode方法的情况下,可以姑且的认为等于一个内存地址的一个标志,但是毕竟是hash算法,肯定会存在hash冲突的情况,这里就不深究下去了。所以Java明确告诉你判断两个对象是否相等用的是equals方法,除了你自己,JVM也不知道这两个对象是否相等。

2、为什么要使用hashCode

看完了上述的描述之后,我们就可以得到答案了,就是回归点题的问题,它存在的必要性就是加速两个对象的判断过程。
还有其二,其二就是方便于hash表的使用,hash表可以根据这个hashCode去计算一个实用的hash码做hash处理。

3、如何正确的使用hashCode

正确使用hashCode码的方式无非就是老生长谈的equals跟hashCode的问题。那就是如果重写了equals的时候,一定要重写hashCode方法。一般来说可以自己根据业务逻辑设计一个hash算法,算出两个对象是否相等,而不仅仅使用内存地址。特别要注意的是在hashMap中去使用这个的时候。

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值