重写hashcode方法需要重写equals方法吗?为什么?

        这个问题其实是一个非常值得探讨的问题,首先我们必须先知道,hashcode与equals方法到底是什么东西?

         这个是在最顶层父类的hashcode与equals方法,看过我之前文章的朋友一定知道,native关键字的意义,这个其实是可以用别的语言在java中来操作底层的东西。

        下面是我翻译的java对于hashcode的官方注解:

/**
     * 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
     */

返回对象的哈希码值。这种方法是 * 支持哈希表,例如提供的哈希表 * {@link java.util.HashMap}。 * <p> * {@code hashCode} 的通用合约为: * <ul> * <li>每当它在同一个对象上被多次调用时 * Java 应用程序的执行,{@code hashCode} 方法 * 必须始终返回相同的整数,不提供任何信息 * 用于对象的 {@code equals} 比较被修改。 * 这个整数不需要在一次执行中保持一致 * 应用程序到另一个执行相同的应用程序。 * <li>如果两个对象根据{@code equals(Object)}相等 * 方法,然后对每个调用 {@code hashCode} 方法 * 两个对象必须产生相同的整数结果。 * <li><em>不</em>要求两个对象不相等 * 根据 {@link java.lang.Object#equals(java.lang.Object)} * 方法,然后在每个对象上调用 {@code hashCode} 方法 * 两个对象必须产生不同的整数结果。但是,那 * 程序员应该知道产生不同的整数结果 * 对于不相等的对象可能会提高哈希表的性能。 * </ul> * <p> * 在合理可行的情况下,hashCode 方法定义为 * 类 {@code Object} 确实为不同返回不同的整数 * 对象。 (这通常是通过转换内部实现 * 将对象的地址转换成整数,但是这个实现 *技术不是必需的 * Java&trade;编程语言。) * * @return 此对象的哈希码值。 * @see java.lang.Object#equals(java.lang.Object) * @see java.lang.System#identityHashCode

        首先这个注解是非常官方的,虽然翻译过来很生硬但是外面还是读出很多关键信息。

1.hashcode方法返回的哈希吗值,这个值的计算是基于哈希表与哈希算法的。Java中的hashCode方法就是根据一定的规则将与对象相关的信息(比如对象的存储地址,对象的字段等)映射成一个数值,这个数值称作为散列值。

2.在一个程序被执行的期间,同一个对象必须返回相同的hashcode值。

3.如果两个对象根据equals(Object)产生相同的返回值,那么它们的hashcode值就必须相等。但是两个对象不相同确实也可能会返回相同的hashcode值。这个就被称为“哈希冲突”

4.hash值通常是通过内部转换实现的,将对象的地址转换为整数,但是这个技术不是依靠java语言实现的。

        通过管反复注解的阅读我们已经明白了,什么是hashcode。但是这么用的意义到底在哪里呢?其实我们仔细思考,java就采用了hash表,利用哈希算法(也叫散列算法),就是将对象数据根据该对象的特征使用特定的算法将其定义到一个地址上,那么在后面定义进来的数据只要看对应的hashcode地址上是否有值,如果有那么就用equals比较,如果没有则直接插入,只要就大大减少了equals的使用次数,执行效率就大大提高了。这样我们就不用一次次去比较地址,这样对程序的速率提升是巨大的。

        所以我们不难理解hashcode不能代替地址,它只是基于地址的映射。根据 {@code hashCode} 的通用合约:两个对象的地址相同,那么它们的hashcode值就必须相同。而对应的是两个对象的hashcode值不同那么它们的地址就一定不同。但是存在两个地址不同但是hashcode值相同的情况。哈希类存储结构(HashSet、HashMap等等)添加元素会有重复性校验,校验的方式就是先取hashCode判断是否相等(这个位置通过哈希算法可能存在多个元素),这个时候即需要通过equals方法比较(极大缩小比较范围,高效判断),最终判定该存储结构中是否有重复元素。

        所以对于这个问题重写equals方法就一直要重写hashcode方法。但是如果你是要重写hashcode方法就不一定需要重写equals方法。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值