浅显易懂说 hashCode() equals()

hashCode()   equals() 的逻辑关系是很抽象的。

首先要弄明白两个原理

1,为什么不同的对象,会在特殊情况下却有相同的hashCode。可以举个例子吗?

这个涉及数据结构的知识,目前我正在研究这个问题,以后探讨。

2,两个相同的对象,hashCode一定是相同的。

根据上面的推导,java已经规范出来:

1,equals()相等那么hashCode()一定相等, 其中equals表示业务意义上相等的两个对象。这个根据原理2推导出

比如:

2,hashCode()相等 那么equals可以相等,也可以不相等,这个就是根据原理1推导出来

结论说明:

在java语言里面的那些 HashSet 和HashMap集合就根据上面的两条规范来设计的。具有去除相同对象的功能。

HashMap添加集合的时候,就是先用对象的hashCode定位数组槽位,然后比较equals是否相等。意思就是:hashCode相等,

equals也有可能不等,所以还要比较一下equals。如果比较有相同的equals,就覆盖去重了,比较不同,就追加到链表后。

因为两个不同的对象在特殊情况下也会有相等的hashCode,就是最开始说的那个原理1。

最后我们写程序的时候,用到hashSet和hashMap的时候,就要遵守上面的规范。

示例过程:

Student stu = new Student(1, "AAA");
Student stu2 = new Student(1, "AAA");

stu 和 stu2,我们在编程的时候,业务意义上一定要作为相等对象处理。既然是相等的对象那么hashCode一定是相等的。

所以我们要重写 equals() 和 hashCode();

public class Student {
private int id;
private String name;

public Student(int id, String name) {
this.id = id;
this.name = name;
}

@Override
public boolean equals(Object o) {
// 就是比较一下 成员变量id和name的值是否相同。
return id == student.id &&
Objects.equals(name, student.name);
}

@Override
public int hashCode() {
//也是根据成员变量 id 和 name的值去换算,如果 两个对象的 id 和 name都相同的话,会返回一样的hashCode。
return Objects.hash(id, name);
}

}

Student stu = new Student(1, "AAA");
Student stu2 = new Student(1, "AAA");
HashSet<Student> set = new HashSet<>();
set.add(stu);
set.add(stu2);
for (Student student : set) {
System.out.println(student);
}
打印结构只有一个对象,可以去重,是正确的。

如果我们违背了上面的规范,比如 写个 equals相等,hashCode不等的实例代码,如下:

下面的程序没有重写hashCode方法,就利用了父类Object的hashCode,那么Object的hashCode,就不管你业务上的 id值和name值了,

返回的hashCode就基本上是不相等的。

public class Student {
private int id;
private String name;

public Student(int id, String name) {
this.id = id;
this.name = name;
}

@Override
public boolean equals(Object o) {
// 就是比较一下 成员变量id和name的值是否相同。
return id == student.id &&
Objects.equals(name, student.name);
}


}

Student stu = new Student(1, "AAA");
Student stu2 = new Student(1, "AAA");
HashSet<Student> set = new HashSet<>();
set.add(stu);
set.add(stu2);
for (Student student : set) {
System.out.println(student);
}
打印结果:两个对象,不可以去重,是有bug的。

 


 

posted @ 2020-08-27 12:11  会游泳的小猪  阅读(194)  评论(0)    收藏  举报