上一篇地址:持续总结中!2024年面试必问 100 道 Java基础面试题(三十七)-CSDN博客
七十五、两个对象equals相等,hashCode也相等么?
在Java中,如果两个对象通过 equals()
方法比较结果为相等,那么它们的 hashCode()
方法也必须返回相同的值。这是Java平台的核心约定之一,对于维护基于哈希表的集合(如 HashMap
、HashSet
)的完整性至关重要。
为什么 equals
相等时,hashCode
也必须相等?
-
集合行为:当对象作为键存储在哈希表集合(如
HashMap
或HashSet
)中时,集合会根据对象的hashCode()
值来决定对象的存储位置。如果两个对象的hashCode()
值不同,即使它们通过equals()
方法比较是相等的,集合也会认为它们是不同的键,从而导致逻辑错误。 -
性能:一致的
hashCode()
实现可以确保相等的对象被存储在哈希表的相同位置,这样可以提高查找、插入和删除操作的性能。 -
正确性:如果违反了这个约定,即两个通过
equals()
比较相等的对象返回了不同的hashCode()
值,那么基于哈希表的集合可能无法正确地存储、检索或删除这些对象。
示例代码
import java.util.Objects;
public class MyObject {
private int id;
private String name;
public MyObject(int id, String name) {
this.id = id;
this.name = name;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
MyObject myObject = (MyObject) o;
return id == myObject.id && Objects.equals(name, myObject.name);
}
@Override
public int hashCode() {
return Objects.hash(id, name);
}
}
public class Main {
public static void main(String[] args) {
MyObject obj1 = new MyObject(1, "Object1");
MyObject obj2 = new MyObject(1, "Object1");
if (obj1.equals(obj2) && obj1.hashCode() == obj2.hashCode()) {
System.out.println("Both objects are equal and have the same hash code.");
} else {
System.out.println("The objects are not equal or have different hash codes.");
}
}
}
在这个示例中,MyObject
类重写了 equals()
和 hashCode()
方法。当两个 MyObject
对象的 id
和 name
属性相同时,它们通过 equals()
方法比较结果为相等,并且它们的 hashCode()
方法返回相同的值。
注意事项
- 仅当
equals()
方法被重写以提供有意义的对象比较逻辑时,才应该重写hashCode()
方法。 - 如果对象的属性发生变化,导致
equals()
方法比较结果为不相等,那么hashCode()
方法也应该返回不同的值。 - 在某些情况下,如对象的逻辑状态可能变化,可能需要重新计算
hashCode()
。
总结来说,当两个对象通过 equals()
方法比较相等时,它们的 hashCode()
方法也应该返回相同的值,这是Java集合框架正确工作的基本要求。
七十六、两个对象hashCode相等,equals也相等么?
在Java中,如果两个对象的hashCode()
方法返回相同的值,这并不意味着这两个对象通过equals()
方法比较也一定相等。这种现象通常被称为“哈希冲突”(Hash Collision),它是哈希表设计中的一个固有特性。
hashCode()
与equals()
的关系
根据Java的官方文档和最佳实践,以下是hashCode()
与equals()
方法之间的关系:
-
等价性:如果两个对象通过
equals()
方法比较是相等的,那么它们的hashCode()
方法必须返回相同的值。 -
非等价性:如果两个对象通过
equals()
方法比较不相等,那么它们的hashCode()
方法可以返回相同或不同的值。但是,为了提高哈希表的性能,建议在对象不相等时产生不同的哈希码。
示例代码
import java.util.Objects;
class User {
private int id;
private String name;
public User(int id, String name) {
this.id = id;
this.name = name;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
User user = (User) o;
return id == user.id;
}
@Override
public int hashCode() {
// 简单的哈希码实现,基于id属性
return Objects.hash(id);
}
}
public class HashCodeEqualsExample {
public static void main(String[] args) {
User user1 = new User(1, "Alice");
User user2 = new User(1, "Bob");
// hashCode相同,但通过equals比较不相等
System.out.println(user1.hashCode() == user2.hashCode()); // true
System.out.println(user1.equals(user2)); // false
}
}
在这个示例中,User
类的hashCode()
方法仅基于id
属性生成哈希码,而equals()
方法比较了id
属性。尽管user1
和user2
的hashCode()
值相同,但它们通过equals()
方法比较是不相等的,因为它们的name
属性不同。
注意事项
- 哈希码的一致性:在对象的整个生命周期中,如果用来比较相等性的属性没有变化,那么
hashCode()
方法的返回值也不应该变化。 - 哈希码的分布:一个好的哈希码实现应该尽量分散,以减少哈希冲突,提高哈希表的性能。
- 哈希冲突的处理:在处理哈希表时,应该意识到即使
hashCode()
值相同,对象也可能不相等,因此通常需要通过equals()
方法进行比较。
总结来说,两个对象的hashCode()
值相等并不意味着它们通过equals()
方法比较也相等。这是哈希表设计中的一个基本理解,正确处理这种情况对于确保哈希表的正确性和性能至关重要。