前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >为什么重写equals()方法时必须重写hashCode()方法【详解】

为什么重写equals()方法时必须重写hashCode()方法【详解】

作者头像
訾博ZiBo
发布于 2025-01-06 05:51:24
发布于 2025-01-06 05:51:24
18000
代码可运行
举报
运行总次数:0
代码可运行

一、为什么重写equals()方法时必须重写hashCode()方法

1、关于hashCode()的约定

hashCode()方法源码注释:
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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.

意思就是:如果两个对象根据equals()方法比较是相等的,那么调用这两个对象的hashcode()方法也必须产生相同的结果;

2、equals()方法和hashCode()方法的关系

  • 如果两个对象相同(即:用 equals 比较返回true),那么它们的 hashCode 值一定要相同;
  • 如果两个对象的 hashCode 值相同,但是它们并不一定相同(即:用 equals 比较返回 false);

3、为什么一定要使用 hashcode() 方法

根本原因是为了提升程序运行效率

hashCode()方法返回一个hashCode值,实际上就是一个int整数;

hashCode值的作用是确定该对象在哈希表中的索引位置;

根据上面equals()和hashCode()的关系,我们在比较两个对象是否相同的时候可以先比较他们的hashCode值,如果hashCode值不同的话就没有必要再使用equals()进行比较了,因为使用equals()进行比较本身就是一个低效率的过程;

举例说明:

我们都知道list集合是有序的,可以重复,set集合是无序的,不可以重复,那么怎么保证放入的元素不重复呢?仅仅使用equals()方法是不可能的,比如要存放第10001个元素,难道要与前面10000个元素挨个equals()比较吗?这效率太低了,因此hashCode就应运而生了!Java就采用了哈希表,利用哈斯算法(也叫散列算法),将对象数据根据其特征使用特定的算法将其定义到一个地址上,那么在后面存放进来的数据只需要首先判断对应的地址是否有数据,如果有就先比较它们的hashCode是否相等,如果相等就再使用equals()比较内容是否相同,反之直接插入,(同样,比较两个对象是否相同,也可以先比较两个对象的hashCode是否相等,如果相等再进行equals()比较,反之直接返回false即可)这样就大大减少了使用equals()的次数,提升了程序运行效率

简而言之,重写hashcode()方法的目的就是:保证使用equals()方法比较相同的对象,所对应的hashCode值也相同的;

4、HashMap结构

参考文章:

复习一波HashMap底层实现原理解析https://blog.csdn.net/qq_37840993/article/details/108048597

HashMap结构:数组 + 链表(或红黑树(JDK8开始),当链表长度超过8,就会转成红黑树,以提高查询效率);

HashMap结构图:

5、重写hashcode()方法演示

代码演示:
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package com.zibo.java.february.second;

public class MyEquals {
    public static void main(String[] args) {
        Student s1 = new Student("訾博", 24);
        Student s2 = new Student("訾博", 24);
        System.out.println(s1.equals(s2)); // true
        System.out.println(s1.hashCode());
        System.out.println(s2.hashCode());
    }
}
class Student{
    private String name;
    private int age;

    public Student() {
    }

    public Student(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    // 咱们来手动定制equals()方法
    @Override
    public boolean equals(Object o) {
        // 两个对象堆内存地址相同,说明是同一个对象,自然内容也相同
        if(this == o){
            return true;
        }
        // 先判断是否是一个Student的实例对象,如果是向下转型进行比较,反之直接返回false
        if(!(o instanceof Student)){
            return false;
        }
        // 向下转型,继续判断每个值是否相等
        Student student = (Student)o;
        return this.name.equals(student.name) && this.age == student.age;
    }

    // 我这里使用idea一键重写了,具体该怎么重写hashCode()方法、有什么规则,暂不讨论
    @Override
    public int hashCode() {
        int result = name != null ? name.hashCode() : 0;
        result = 31 * result + age;
        return result;
    }
}
运行结果:

(如果没有重写hashCode()方法,下面两个int值是不同的,因为Object类默认实现的hashCode()方法是根据对象所存储的的堆内存地址计算出来的,既然是两个对象堆内存地址自然不同,因此hashCode不同!)

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
true
34671292
34671292
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2025-01-06,如有侵权请联系 cloudcommunity@tencent.com 删除

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

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、为什么重写equals()方法时必须重写hashCode()方法
    • 1、关于hashCode()的约定
      • hashCode()方法源码注释:
    • 2、equals()方法和hashCode()方法的关系
    • 3、为什么一定要使用 hashcode() 方法
      • 举例说明:
    • 4、HashMap结构
      • 参考文章:
      • HashMap结构图:
    • 5、重写hashcode()方法演示
      • 代码演示:
      • 运行结果:
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档