Java基础面试题06:hashCode()和equals()方法的重要性体现在什么地方?

前言

Java中的hashCode()equals()方法看似是干同一件事,但它们的使用场景和作用却大有不同。为了让程序更高效、更准确地运行,我们需要对这两者有深入的了解,并掌握它们的重写规则。

hashCode()和equals()的基础知识

什么是hashCode?

hashCode()是用来返回一个哈希值 (int类型)的,它的作用是确定对象在散列表(如HashMapHashSet)中的存储位置。

java 复制代码
public class Demo {
    public static void main(String[] args) {
        String str = "aa";
        System.out.println(str.hashCode());  // 输出结果为3104
    }
}
  • 哈希值的作用
    可以把哈希值看成是对象的身份证号,散列表会根据这个"身份证号"快速定位到对象的位置。
  • 定义在哪
    hashCode()方法定义在java.lang.Object类中,这意味着所有类都默认拥有这个方法。

什么是equals?

equals()方法用于比较两个对象是否"相等"。

默认情况下,它和==一样,比较的是对象的内存地址 。但是,开发中我们经常需要比较对象的内容,比如两个学生对象的名字是否相等,这时就需要重写equals()方法。


hashCode()和equals()的关系

两条重要结论

  1. 如果两个对象通过equals()方法比较相等,它们的hashCode()值必须相等
    (也就是说:equals()是绝对可靠的。)
  2. 如果两个对象的hashCode()值相等,它们通过equals()方法比较时不一定相等
    (这意味着:hashCode()是相对可靠的。)

这两个结论很重要,后面会用它们来解释为什么要同时重写hashCode()equals()


为什么要重写equals()?

默认情况下,equals()方法比较的是两个对象的内存地址。如果两个对象的地址不同,即使它们的内容完全一样,equals()也会返回false

举个例子:

java 复制代码
class Person {
    String name;

    Person(String name) {
        this.name = name;
    }
}

public class Demo {
    public static void main(String[] args) {
        Person p1 = new Person("Alice");
        Person p2 = new Person("Alice");

        System.out.println(p1.equals(p2));  // false
    }
}

如何重写equals()?

如果我们希望两个name相同的Person对象被认为是相等的,就需要重写equals()方法:

java 复制代码
@Override
public boolean equals(Object obj) {
    if (this == obj) return true; // 自反性
    if (obj == null || getClass() != obj.getClass()) return false;
    Person person = (Person) obj;
    return Objects.equals(name, person.name);
}

重写equals()需要遵守的规则

  • 自反性x.equals(x)必须返回true
  • 对称性 :如果x.equals(y)true,那么y.equals(x)也必须为true
  • 传递性 :如果x.equals(y)true,并且y.equals(z)true,那么x.equals(z)也必须为true
  • 一致性 :如果两个对象没有变化,多次调用x.equals(y),结果必须一致。
  • 非空性x.equals(null)必须返回false

为什么要重写hashCode()?

当我们重写了equals(),还必须重写hashCode()

这是因为,如果两个对象被认为是相等的(通过equals()),它们必须有相同的哈希值,否则会影响集合类(如HashSetHashMap)的正常工作。

举个例子:

假设我们有两个内容相同的Person对象:

java 复制代码
Person p1 = new Person("Alice");
Person p2 = new Person("Alice");
  • 如果只重写了equals()
    • HashSet可能会认为它们是两个不同的对象,导致HashSet中存储了重复数据。
  • 如果同时重写了hashCode()
    • HashSet会根据相同的哈希值,将它们识别为同一个对象,避免重复存储。

重写hashCode()的方法

在重写hashCode()时,应该确保相等的对象有相同的哈希值 。通常,可以通过Objects.hash()方法快速生成哈希值。

java 复制代码
@Override
public int hashCode() {
    return Objects.hash(name);
}

总结:hashCode()和equals()的搭配使用

简单记住:

  1. 如果重写了equals(),一定要重写hashCode()
  2. equals()保证逻辑上的相等,hashCode()保证性能上的高效。

两者的重要性体现在:

  • 在集合类中(如HashSetHashMap),hashCode()用于快速定位,equals()用于最终确认是否相等。
  • 通过正确重写这两个方法,可以避免重复数据、保证集合操作的准确性。

参考代码示例:综合重写equals()和hashCode()

java 复制代码
class Person {
    String name;

    Person(String name) {
        this.name = name;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null || getClass() != obj.getClass()) return false;
        Person person = (Person) obj;
        return Objects.equals(name, person.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name);
    }
}

public class Demo {
    public static void main(String[] args) {
        Person p1 = new Person("Alice");
        Person p2 = new Person("Alice");

        System.out.println(p1.equals(p2));  // true

        HashSet<Person> set = new HashSet<>();
        set.add(p1);
        set.add(p2);

        System.out.println(set.size());  // 1
    }
}

通过这个示例,可以看到两个name相同的Person对象在HashSet中只存储一次。


掌握了这些,你就能够在面试中清晰地解释hashCode()equals()的作用及它们之间的关系啦!

最后说一句(求关注,求赞,别白嫖我)

最近无意间获得一份阿里大佬写的刷题笔记,一下子打通了我的任督二脉,进大厂原来没那么难。 这是大佬写的 7701页的BAT大佬写的刷题笔记,让我offer拿到手软

本文,已收录于,我的技术网站 cxykk.com:程序员编程资料站,有大厂完整面经,工作技术,架构师成长之路,等经验分享

求一键三连:点赞、分享、收藏

点赞对我真的非常重要!在线求赞,加个关注我会非常感激!

相关推荐
计算机毕业设计小帅21 小时前
【2026计算机毕业设计】基于Springboot的校园电动车短租平台
spring boot·后端·课程设计
调试人生的显微镜21 小时前
Web前端开发工具实战指南 从开发到调试的完整提效方案
后端
静心观复21 小时前
drawio画java的uml的类图时,class和interface的区别是什么
java·uml·draw.io
Java水解21 小时前
【SQL】MySQL中空值处理COALESCE函数
后端·mysql
Laplaces Demon21 小时前
Spring 源码学习(十四)—— HandlerMethodArgumentResolver
java·开发语言·学习
guygg8821 小时前
Java 无锁方式实现高性能线程
java·开发语言
ss27321 小时前
手写Spring第7弹:Spring IoC容器深度解析:XML配置的完整指南
java·前端·数据库
Python私教21 小时前
DRF:Django REST Framework框架介绍
后端·python·django
间彧21 小时前
Java HashMap如何合理指定初始容量
后端
用户40993225021221 小时前
PostgreSQL全表扫描慢到崩溃?建索引+改查询+更统计信息三招能破?
后端·ai编程·trae