上篇 关于 equals 和 hashCode 关于 equals 和 hashCode 的基本性质已经论述过了。
1.什么时候应该覆盖 equals?
我们知道 equals 默认比较的内存地址,即是否为同一个对象。如果类具有了自己特有的逻辑相等,即属性值等,的概念时,并且超类没有覆盖或者覆盖了单不满足子类需求的情况下重写 equals。
但对于类似枚举类这样的 class 而言,每个属性最多只存在一个对象,逻辑相等与内存地址相等时一样的,不需要重写。
2.为什么要覆盖 equals( hashCode) ?
/**
* @author shengjk1
* @date 2020/3/14
*/
public class TestEquals {
public static void main(String[] args) {
HashMap<Student, String> map = new HashMap<>();
Student student = new Student(16, "小明");
map.put(student, "a");
Student student1 = new Student(16, "小明");
System.out.println(map.containsKey(student1));
}
}
class Student {
private int age;
private String name;
public Student(int age, String name) {
this.age = age;
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
// @Override
// public boolean equals(Object o) {
// if (this == o) return true;
// if (o == null || getClass() != o.getClass()) return false;
// Student student = (Student) o;
// return age == student.age &&
// Objects.equals(name, student.name);
// }
//
@Override
public int hashCode() {
return Objects.hash(age, name);
}
}
结果
false
这完全不是我们想要的,我们希望的是 map.containsKey(student1) 为true。但为什么是 false 呢?通过源码我们可以知道 应为 equals 不等,导致的。同理,对于 hashCode 也是如此。
3.是否是任何时候都需要覆盖 equals 和hashCode?
答案是 否定的。
还记得上一篇说过的吗,JDK 内部就有违背 equals hashCode 一致性规则的。另外的话,hashCode 仅仅针对 hash 表来说才有用。
/**
* @author shengjk1
* @date 2020/3/14
*/
public class TestEquals {
public static void main(String[] args) {
HashMap<Student, String> map = new HashMap<>();
Student student = new Student(16, "小明");
map.put(student, "a");
Student student1 = new Student(16, "小明");
System.out.println("map " + map.containsKey(student1));
ArrayList<Student> students = new ArrayList<>();
students.add(student);
System.out.println("list " + students.contains(student1));
}
}
class Student {
private int age;
private String name;
public Student(int age, String name) {
this.age = age;
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return age == student.age &&
Objects.equals(name, student.name);
}
//
// @Override
// public int hashCode() {
// return Objects.hash(age, name);
// }
}
结果
map false
list true
对于 list 而言,根本就不需要 比较hashCode,我们也违背了 equals 与 hashCode 的一致性,但对于 students.contains(student1) 结果就是正确的
4.总结
1.java 集合内部比较对象是否相等一般用的都是 equals ,所以 equals 是要尽量重写的。
2.而对于 hashCode 来说,对于 hash table 来说是必须要重写的,其他的可以不重写。
网友评论