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:程序员编程资料站,有大厂完整面经,工作技术,架构师成长之路,等经验分享

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

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

相关推荐
雯0609~4 分钟前
C#-winform:项目打包
开发语言·c#
桃园码工20 分钟前
第三章:基本语法 1.注释 --Go 语言轻松入门
开发语言·后端·golang·轻松入门·go 语言
白子寰37 分钟前
【C++打怪之路Lv16】-- map && set
开发语言·c++
沐风ya37 分钟前
python代码示例(读取excel文件,自动播放音频)
开发语言·python
YCyjs40 分钟前
k8s之Helm
java·容器·kubernetes
sg_knight1 小时前
RabbitMQ的预取值详解
java·分布式·微服务·消息队列·rabbitmq
終不似少年遊*1 小时前
Python开发环境搭建+conda管理环境
开发语言·笔记·python·学习·conda
froginwe111 小时前
HTML DOM 修改 HTML 内容
开发语言
借雨醉东风1 小时前
C++实现网格交易的例子
开发语言·c++·算法
失眠的树亚1 小时前
报错:java: 无法访问org.springframework.boot.SpringApplication
java·spring boot·spring