前言
Java中的hashCode()
和equals()
方法看似是干同一件事,但它们的使用场景和作用却大有不同。为了让程序更高效、更准确地运行,我们需要对这两者有深入的了解,并掌握它们的重写规则。
hashCode()和equals()的基础知识
什么是hashCode?
hashCode()
是用来返回一个哈希值 (int类型)的,它的作用是确定对象在散列表(如HashMap
或HashSet
)中的存储位置。
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()的关系
两条重要结论
- 如果两个对象通过
equals()
方法比较相等,它们的hashCode()
值必须相等 。
(也就是说:equals()
是绝对可靠的。) - 如果两个对象的
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()
),它们必须有相同的哈希值,否则会影响集合类(如HashSet
、HashMap
)的正常工作。
举个例子:
假设我们有两个内容相同的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()的搭配使用
简单记住:
- 如果重写了
equals()
,一定要重写hashCode()
。 equals()
保证逻辑上的相等,hashCode()
保证性能上的高效。
两者的重要性体现在:
- 在集合类中(如
HashSet
、HashMap
),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:程序员编程资料站,有大厂完整面经,工作技术,架构师成长之路,等经验分享
求一键三连:点赞、分享、收藏
点赞对我真的非常重要!在线求赞,加个关注我会非常感激!