事件
今天同事跑过来问我,我用list判断是否包含对象,我只重写了equals方法,居然可以正确判断,不是说重写equals就必须重写hashCode么?我让她看看ArrayList的 contains 方法,然后她就明白了。
== :它计算的是操作数的值之间的关系,如果是基本数据类型,值相等即可,如果是引用类型,内存地址要一样
equals : Object 的 实例方法,比较两个对象的content是否相同
hashCode : Object 的 native方法 , 获取对象的哈希值,用于确定该对象在哈希表中的索引位置,它实际上是一个int型整数
文字表达太空洞了,我们直接上代码
不重写 equals 也不重写 hashCode
class Student {
public Student(String name, Integer age) {
this.name = name;
this.age = age;
}
private String name;
private Integer age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public static void main(String[] args) {
Student student1 = new Student("张三", 1);
Student student2 = new Student("张三", 2);
System.out.println("==:" + (student1 == student2));
System.out.println("equals:" + (student1.equals(student2)));
System.out.println("student1 hashCode:" + student1.hashCode() + ",student2 hashCode:" + student2.hashCode());
Set<Student> set = new HashSet<>();
set.add(student1);
set.add(student2);
System.out.println("set的大小:" + set.size());
List<Student> list = new ArrayList<>();
list.add(student1);
System.out.println("list contains:" + list.contains(student2));
}
}
运行结果:
==:false
equals:false
student1 hashCode:30852576,student2 hashCode:20929316
set的大小:2
list contains:false
没有重写equals 所以也是false
hashSet 无序,不能重复,大小是2说明 是两个对象
list 是有序集合,可重复 包含 是两个对象,所以是false
只重写 equals 不重写 hashCode
此时equals等,hashCode不等
class Student {
public Student(String name, Integer age) {
this.name = name;
this.age = age;
}
private String name;
private Integer age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (obj.getClass() != this.getClass()) {
return false;
}
return this.getName().equals(((Student) obj).getName());
}
public static void main(String[] args) {
Student student1 = new Student("张三", 1);
Student student2 = new Student("张三", 2);
System.out.println("==:" + (student1 == student2));
System.out.println("equals:" + (student1.equals(student2)));
System.out.println("student1 hashCode:" + student1.hashCode() + ",student2 hashCode:" + student2.hashCode());
Set<Student> set = new HashSet<>();
set.add(student1);
set.add(student2);
System.out.println("set的大小:" + set.size());
List<Student> list = new ArrayList<>();
list.add(student1);
System.out.println("list contains:" + list.contains(student2));
}
}
==:false
equals:true
student1 hashCode:30852576,student2 hashCode:20929316
set的大小:2
list contains:true
equals 肯定是true,因为重写了equals方法,name值一样,所以是true
hashCode 不一样 hashSet 也认为是两个值
list 是包含的,我们看下ArryList contains 实现
对比的就是equals方法,所以集合判断是否包含只需重写 equals 就可以了
只重写 hashCode 不重写 equals
此时 hashCode等,但是equals不等
class Student {
public Student(String name, Integer age) {
this.name = name;
this.age = age;
}
private String name;
private Integer age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
/* @Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (obj.getClass() != this.getClass()) {
return false;
}
return this.getName().equals(((Student) obj).getName());
}*/
@Override
public int hashCode() {
return getName().hashCode();
}
public static void main(String[] args) {
Student student1 = new Student("张三", 1);
Student student2 = new Student("张三", 2);
System.out.println("==:" + (student1 == student2));
System.out.println("equals:" + (student1.equals(student2)));
System.out.println("student1 hashCode:" + student1.hashCode() + ",student2 hashCode:" + student2.hashCode());
Set<Student> set = new HashSet<>();
set.add(student1);
set.add(student2);
System.out.println("set的大小:" + set.size());
List<Student> list = new ArrayList<>();
list.add(student1);
System.out.println("list contains:" + list.contains(student2));
}
}
运行结果:
==:false
equals:false
student1 hashCode:774889,student2 hashCode:774889
set的大小:2
list contains:false
跟equals相关的都是false了,此时hashCode等,但是equals 不等 hash对比的也认为是两个对象,我们用HashMap,和 HashSet都可以测试。
重写 equals 和 hashCode
此时 equals等,是hashCode等
class Student {
public Student(String name, Integer age) {
this.name = name;
this.age = age;
}
private String name;
private Integer age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (obj.getClass() != this.getClass()) {
return false;
}
return this.getName().equals(((Student) obj).getName());
}
@Override
public int hashCode() {
return getName().hashCode();
}
public static void main(String[] args) {
Student student1 = new Student("张三", 1);
Student student2 = new Student("张三", 2);
System.out.println("==:" + (student1 == student2));
System.out.println("equals:" + (student1.equals(student2)));
System.out.println("student1 hashCode:" + student1.hashCode() + ",student2 hashCode:" + student2.hashCode());
Set<Student> set = new HashSet<>();
set.add(student1);
set.add(student2);
System.out.println("set的大小:" + set.size());
List<Student> list = new ArrayList<>();
list.add(student1);
System.out.println("list contains:" + list.contains(student2));
}
}
运行结果
==:false
equals:true
student1 hashCode:774889,student2 hashCode:774889
set的大小:1
list contains:true
此时 hash对比的才认为是一个对象,hash对比的操作 必须重写 equals 和 hashCode
总结
在重写 equals 的时候,我们可以根据实际情况来判断,并非说 重写 equals 就必须重写 hashCode
如果是 集合对比,重写 equals 即可
如果是 hash对比,比如 HashMap,HashSet 就需要重写 equals和hashCode 了。
我说的可能不对哈,请高人在评论区指出我的错误。