怎么重写equals()方法和hashCode()方法
怎么重写equals()方法和hashCode()方法
重写 equals()
方法
equals()
方法用于判断两个对象是否相等。默认情况下,Object
类的 equals()
方法是通过引用比较的,因此两个不同的对象即使内容相同也会返回 false
。要重写 equals()
方法,通常遵循以下步骤:
-
检查引用:首先检查是否是同一个对象。
-
检查类型:确保传入的对象与当前对象属于相同的类。
-
强制类型转换:将传入的对象转换为当前类的类型。
-
比较字段:逐个比较对象的字段。
注意:比较顺序不一样也会影响性能
最常不相等的字段优先:假设 studentId 是最常不相等的字段,将其放在最前面进行比较。 计算成本低的字段优先:age 是一个基本类型,计算成本低,放在 studentId 之后进行比较。 其他字段:最后比较 name 字段。 通过这样的顺序安排,可以有效提高 equals() 方法的性能。
重写 hashCode()
方法
hashCode()
方法返回对象的哈希码。对于重写 equals()
方法的类,必须重写 hashCode()
方法,以确保相等的对象具有相同的哈希码。通常遵循以下步骤:
-
使用字段生成哈希值:选择参与相等性比较的字段来计算哈希值。
-
使用合适的算法:通常使用乘法和加法的组合来生成哈希值。
重写 hashCode()
方法注意事项:
重写 hashCode() 方法时,应遵循以下原则和步骤,以确保哈希码的合理性和一致性: 选择属性:选择对象中对等性(equals 方法)有影响的属性。 计算哈希码:为每个选定的属性计算哈希码。 组合哈希码:将各个属性的哈希码组合成一个最终的哈希码值。 返回结果:返回组合后的哈希码值。
17常用作为初始值,31常用作系数
首先为了尽量让产生hashcode保持唯一,所以一定使用一个素数来做系数(这里的31) 但为什么是31而不是别的素数呢? 因为31属于一个特殊的质数 任何数 乘以 31 就等于 这个数 * 2 的5次方 - 这个数本身 <<左移几位 表示 乘以 2 的几次方 >>右移几位 标识 除以 2 的几次方 n * 31 等价于 (n * 2 * 2* 2 * 2 * 2 - n)即 (n << 5) - n
代码示例:
public class Student { private String name; private String studentId; public Student(String name, String studentId) { this.name = name; this.studentId = studentId; } // 重写 equals 方法 @Override public boolean equals(Object obj) { // 检查是否为同一对象 if (this == obj) { return true; } // 检查对象是否为 null 以及是否属于同一类 if (obj == null || getClass() != obj.getClass()) { return false; } // 将 obj 转换为 Student 类型 Student student = (Student) obj; // 比较姓名和学号 return (name != null ? name.equals(student.name) : student.name == null )&& (studentId != null ? studentId.equals(student.studentId) : student.studentId == null); } // 还应该重写 hashCode 方法 @Override public int hashCode() { int result = 17; // 初始值 result = 31 * result + (name != null ? name.hashCode() : 0); result = 31 * result + (studentId != null ? studentId.hashCode() : 0); return result; } // 其他方法(如 getters 和 toString)可以在这里添加 }
运行验证代码:
public class Main { public static void main(String[] args) { // 创建学生对象 Student student1 = new Student("Alice", "1001"); Student student2 = new Student("Alice", "1001"); Student student3 = new Student("Bob", "1002"); Student student4 = new Student("Alice", "1003"); // 比较学生对象的 equals 方法 System.out.println("Comparing student1 and student2: " + student1.equals(student2)); // true System.out.println("Comparing student1 and student3: " + student1.equals(student3)); // false System.out.println("Comparing student1 and student4: " + student1.equals(student4)); // false // 比较学生对象的 hashCode 方法 System.out.println("Hash code of student1: " + student1.hashCode()); System.out.println("Hash code of student2: " + student2.hashCode()); System.out.println("Hash code of student3: " + student3.hashCode()); System.out.println("Hash code of student4: " + student4.hashCode()); // 检查 hashCode 和 equals 方法的一致性 System.out.println("Hash codes are equal for student1 and student2: " + (student1.hashCode() == student2.hashCode())); // true System.out.println("Hash codes are equal for student1 and student3: " + (student1.hashCode() == student3.hashCode())); // false } }