文章目录
- equals()方法
- hashCode()方法
- [为什么通常需要一起重写 `equals()` 和 `hashCode()`?](#为什么通常需要一起重写
equals()
和hashCode()
?)
equals()方法
equals()
方法是 java.lang.Object
类的一个方法,它用于比较两个对象是否相等。默认情况下,Object
类中的 equals()
方法是通过判断对象的引用是否相等来实现的,也就是说,它比较的是对象在内存中的地址。如果你需要判断两个对象的内容是否相等,你需要重写 equals()
方法。
常见的重写规则:
- 自反性 :对于任何非
null
的对象x
,x.equals(x)
必须返回true
。 - 对称性 :对于任何非
null
的对象x
和y
,如果x.equals(y)
返回true
,那么y.equals(x)
也必须返回true
。 - 传递性 :对于任何非
null
的对象x
、y
和z
,如果x.equals(y)
返回true
且y.equals(z)
返回true
,那么x.equals(z)
也必须返回true
。 - 一致性 :对于任何非
null
的对象x
和y
,如果x.equals(y)
返回true
,那么每次调用x.equals(y)
都必须返回true
,除非对象的状态发生了改变。 - 对
null
的处理 :任何对象与null
比较时都应该返回false
。
示例
java
class Person {
private String name;
private int age;
@Override
public boolean equals(Object obj) {
if (this == obj) return true; // 引用相同,直接返回true
if (obj == null || getClass() != obj.getClass()) return false; // 类型不同或对象为空,返回false
Person person = (Person) obj; // 转换类型
return age == person.age && name.equals(person.name); // 比较属性
}
}
hashCode()方法
hashCode()
方法是 java.lang.Object
类的一个方法,返回一个整数值(哈希码),用于表示对象的内存地址(但并不完全是内存地址)。哈希码用于在基于哈希的集合(如 HashMap
、HashSet
等)中确定对象的位置。
基本规则:
- 如果两个对象通过
equals()
比较返回true
,那么它们的hashCode()
也必须相同。 - 对于相同的对象,每次调用
hashCode()
应该返回相同的值。 - 如果两个对象的
equals()
返回false
,那么它们的hashCode()
不一定要不同,但是不同的哈希码可以提高哈希表的性能(避免哈希冲突)。
为什么通常需要一起重写 equals()
和 hashCode()
?
一致性要求
- Java的集合框架(如
HashSet
、HashMap
等)基于哈希值来存储和查找元素。在这些集合中,首先使用hashCode()
来定位对象可能存储的位置。如果hashCode()
不一致或不正确,可能导致相等的对象被存储到不同的位置,从而影响性能和正确性。 hashCode()
的值用来找到对象在集合中的位置,而equals()
用于实际比较两个对象是否相等。如果这两个方法不一致,就会违反集合框架的基本要求,导致对象查找、删除或更新的异常行为。
哈希表的工作原理
- 在哈希表中,两个相等的对象应该具有相同的哈希值,以便在相同的桶中进行存储和比较
- 如果两个对象的
equals()
返回true
,那么它们必须具有相同的hashCode()
,否则集合框架会误认为它们是不同的对象,导致查找或删除失败。
避免错误的行为
- 比如,在
HashSet
中,添加一个新的对象时,如果它与已经存在的对象相等(即equals()
返回true
),就不应该再添加。如果只重写了equals()
而没有重写hashCode()
,即使两个对象的内容相同,它们也可能被认为是不同的,从而导致错误的添加操作。
例子说明
假设有一个 Person
类,它的 equals()
方法比较 name
和 age
属性。如果不重写 hashCode()
,当我们将两个 Person
对象添加到一个 HashSet
中时,如果这两个对象的 name
和 age
相同,它们在 equals()
上应该返回 true
,但如果它们的 hashCode()
不相同,HashSet
会认为它们是两个不同的对象,从而错误地添加两个相同的对象。
总结
equals()
用于判断两个对象的"内容"是否相等,而hashCode()
用于计算对象的哈希码,帮助集合类确定对象的位置。- 根据 Java 的集合框架约定,如果两个对象相等(即
equals()
返回true
),它们的hashCode()
必须相同。 - 因此,为了确保集合框架的正确行为,通常需要同时重写这两个方法。如果只重写了其中一个,可能导致集合类行为不正确。