上一篇地址:整理好了!2024年最常见 100 道 Java基础面试题(四十)-CSDN博客
八十一、equals 和 hashCode 的区别和联系?
在Java中,equals() 方法和 hashCode() 方法是对象比较和散列表(如 HashMap、HashSet)存储中的关键组成部分。它们之间有紧密的联系,但也存在一些重要的区别。
equals() 方法
 
- 目的:equals()方法用于比较两个对象是否相等。它的默认实现检查对象引用的相等性,即比较是否为同一个对象。
- 重写:在实际应用中,通常需要重写 equals()方法来提供逻辑上的等价性判断,比如比较对象的属性值。
- 使用场景:常用于对象的比较,如在 HashMap中查找特定的键值对。
hashCode() 方法
 
- 目的:hashCode()方法返回对象的散列码(一个整数)。在散列表中,散列码用于确定对象存储的索引位置。
- 重写:当重写 equals()方法时,也应该重写hashCode()方法,以保持两者之间的一致性。
- 使用场景:主要用于散列表的索引操作,如在 HashMap中根据键快速定位到值。
区别
- 功能:equals()是用于比较对象的等价性,而hashCode()是用于生成对象的散列码。
- 返回类型:equals()返回布尔值(boolean),而hashCode()返回一个整数(int)。
- 调用:equals()是在对象间进行比较时显式调用的,hashCode()通常在对象作为散列键时由系统隐式调用。
联系
- 一致性:如果两个对象通过 equals()方法比较是相等的,那么它们的hashCode()方法必须返回相同的散列码。
- 散列表性能:在散列表中,equals()和hashCode()配合使用可以提高查找、插入和删除操作的性能。
重要原则
根据Java的官方文档,重写 equals() 方法时必须遵守以下原则:
- 自反性:对于任何非空引用 x,x.equals(x)应该返回true。
- 对称性:对于任何非空引用 x和y,x.equals(y)应该与y.equals(x)返回相同的结果。
- 传递性:对于任何非空引用 x、y和z,如果x.equals(y)返回true,y.equals(z)返回true,那么x.equals(z)也应该返回true。
- 一致性:对于任何非空引用 x和y,只要在比较过程中它们代表的信息没有被修改,多次调用x.equals(y)应该持续返回相同的结果。
- 非空性:对于任何非空引用 x,x.equals(null)应该返回false。
同时,重写 hashCode() 方法时必须遵守:
- 一致性:在Java应用程序执行期间,只要对象的equals比较所用的信息没有被修改,那么该对象的hashCode值就应该保持不变。
- 等效性:如果两个对象通过equals方法比较是相等的,那么这两个对象调用hashCode方法必须产生相同的整数结果。
- 效率:尽管不严格要求,但建议覆盖hashCode方法的算法能够均匀地分布对象的hashCode值。
示例
public class Person {private String name;private int age;@Overridepublic 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);}@Overridepublic int hashCode() {return Objects.hash(name, age);}
}在这个示例中,Person 类重写了 equals() 方法和 hashCode() 方法,以确保两个 Person 对象在逻辑上相等时,它们的散列码也相同。
总结
equals() 和 hashCode() 是Java中用于对象比较和散列表操作的两个基础方法。它们之间有紧密的联系,尤其是在散列表的使用中。正确实现这两个方法对于确保对象的比较逻辑和散列表的性能至关重要。
八十二、两个对象 equals 相等, hashCode 也相等么?
在Java中,如果两个对象通过 equals() 方法比较结果为相等,那么它们的 hashCode() 方法必须返回相同的散列码。这是 Object 类中 hashCode() 方法的约定,也是实现一个良好的散列表行为的基础。
equals() 方法和 hashCode() 方法的约定
 
根据Java的官方文档,当你重写 equals() 方法时,必须遵守以下与 hashCode() 方法相关的约定:
- 等效性:如果两个对象通过 equals()方法比较是相等的(即x.equals(y)返回true),那么这两个对象调用hashCode()方法必须产生相同的整数结果。
这个约定确保了在散列表(如 HashMap、HashSet)中,相等的对象能够被映射到同一个散列桶(或称为槽位)。
示例
public class Person {private String name;private int age;public Person(String name, int age) {this.name = name;this.age = age;}@Overridepublic 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);}@Overridepublic int hashCode() {return Objects.hash(name, age);}
}在这个示例中,Person 类重写了 equals() 方法和 hashCode() 方法。如果两个 Person 对象具有相同的 name 和 age,它们通过 equals() 方法比较将返回 true,并且它们的 hashCode() 方法将返回相同的散列码。
注意事项
- 如果不遵守这个约定,那么使用相等的对象作为键的散列表(如 HashMap的键)将无法正常工作,因为相等的对象可能会被映射到不同的散列桶,导致无法通过键查找到对应的值。
- 即使两个对象的 equals()方法返回false,它们的hashCode()方法也可能返回相同的散列码,但这并不是一个好的实践,因为它会降低散列表的性能。
总结
两个对象如果通过 equals() 方法比较结果为相等,它们的 hashCode() 方法也应该返回相同的散列码。这是Java中对象相等性和散列码一致性的基本约定,对于维护散列表的完整性和性能至关重要。正确实现这两个方法对于确保对象在集合中的预期行为非常关键。