“equals”与“==”、“hashCode”的区别和使用场景

在Java中,==equals()hashCode()是经常一起使用但具有不同含义和用途的三个概念。

1. == 运算符

==是Java中的一个运算符,它用于比较两个变量的值。对于基本数据类型(如int、char、boolean等),==比较的是它们的实际值。对于引用类型(如对象、数组等),==比较的是对象的内存地址,即判断两个引用是否指向同一个对象。

使用场景:

  • 当你想检查两个引用是否指向同一个对象时(即物理上是同一个对象)。

  • 比较基本数据类型的值是否相等。

示例:

java 复制代码
String str1 = "hello";
String str2 = "hello";
String str3 = new String("hello");

System.out.println(str1 == str2); // true,因为str1和str2都指向字符串常量池中的同一个对象
System.out.println(str1 == str3); // false,因为str3是新建的对象,地址不同

int a = 10;
int b = 10;
System.out.println(a == b); // true,基本类型比较值

2. equals() 方法

equals()Object类中定义的方法,默认实现就是使用==来比较,即比较两个对象的内存地址。但是,很多类(如String、Integer等)重写了equals()方法,使其比较对象的内容(即对象的状态)是否相等。

使用场景:

  • 当你想比较两个对象在逻辑上是否相等时(即内容是否相同),而不是是否同一个对象。

  • 通常,自定义类如果需要比较内容,应该重写equals()方法。

示例:

java 复制代码
String str1 = "hello";
String str3 = new String("hello");

System.out.println(str1.equals(str3)); // true,因为String重写了equals方法,比较的是内容

// 自定义类重写equals的例子
class Person {
    private String name;
    private int age;

    // 构造方法等省略

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

3. hashCode() 方法

hashCode()也是Object类中的方法,它返回对象的哈希码值(一个整数)。哈希码主要用于哈希表(如HashMap、HashSet等)中,用于确定对象在哈希表中的索引位置。

使用场景:

  • 当对象被用于基于哈希的集合(如HashMap、HashSet、Hashtable)时,hashCode()方法会被调用以确定对象的存储位置。

  • 注意:如果两个对象通过equals()方法比较相等,那么它们的hashCode()必须返回相同的值。反之,如果两个对象的hashCode()相同,它们不一定通过equals()比较相等(哈希冲突)。

重写equals()时必须重写hashCode()的原因:

如果两个对象通过equals()比较相等,但它们的hashCode()不同,那么当它们被放入哈希表(如HashMap)时,可能会被放在不同的桶中,从而导致无法正确检索。这违反了hashCode()的通用约定。

示例:

java 复制代码
class Person {
    private String name;
    private int age;

    // 构造方法等省略

    @Override
    public boolean equals(Object obj) {
        // ... 同上
    }

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

总结

  • ==:比较基本数据类型的值或引用类型的内存地址。

  • equals():默认比较内存地址,但通常被重写用于比较对象的内容。

  • hashCode():返回对象的哈希码,用于哈希表。重写equals()时必须重写hashCode(),以保证在哈希表中正确工作。

使用场景:

  • 使用==判断两个引用是否指向同一个对象。

  • 使用equals()判断两个对象在逻辑上是否相等(内容相同)。

  • 使用hashCode()主要是为了在哈希表中快速定位对象。

注意:在重写equals()hashCode()时,要确保满足以下条件:

  1. 自反性:x.equals(x)必须返回true。

  2. 对称性:如果x.equals(y)返回true,则y.equals(x)也必须返回true。

  3. 传递性:如果x.equals(y)返回true,y.equals(z)返回true,则x.equals(z)必须返回true。

  4. 一致性:只要对象没有被修改,多次调用x.equals(y)应该返回相同的结果。

  5. 非空性:x.equals(null)必须返回false。

  6. 如果两个对象通过equals()方法比较相等,那么它们的hashCode()必须返回相同的值。

相关推荐
郑州光合科技余经理20 分钟前
本地生活服务系统:模块边界与结算字段怎么拆
java·开发语言·前端·后端·系统架构·uni-app·php
roman_日积跬步-终至千里43 分钟前
【数据治理(6)】DataOps 不是调度工具,而是让数据产品长期可信的运行机制
java·服务器·网络
来了就未晚44 分钟前
Python基础 学习代码存储与命名规范
开发语言·python·学习
落魄大学生之流水线上谋生计1 小时前
LangGraph 基本用法指南
java·windows·python·langchain
布莱克6051 小时前
数组详解:定义、作用、应用场景及与链表的区别(C/C++ 代码讲解)
c语言·开发语言·c++·数组
2601_962128411 小时前
SpringBoot篇(缓存层)
java·spring boot·缓存
hongmai6668881 小时前
MP2348GTL-Z:这颗24V/4A同步降压芯片,把性能和体积平衡得恰到好处
c语言·开发语言·arm开发·单片机·5g
多弗朗皮卡丘1 小时前
C语言梦开始的地方19:文件操作
c语言·开发语言
Dovis(誓平步青云)1 小时前
折叠屏悬停看视频,上半屏和下半屏应该各做什么
android·java·服务器·开发语言·安全·音视频
benchmark_cc2 小时前
Python量化实战:如何检测并剔除历史数据中的“闪崩/乌龙指”异常价格点?
开发语言·人工智能·python·量化·quantdash·量化数据源