原因总结 :
重要的理论基础:
1、 每个对象都有自己的hashCode()方法,产生哈希值,两个对象的哈希值是可能重复的,这就是哈希冲突,一般通过链表和线性探索来解决哈希冲突问题。
2、对象存储咋内存中的地址是通过hash来确定的。
- 1、重写equals()方法的初衷:我们一般在自定义的实体类中重写equals()方法和hashCode()方法来使得属性值完全相等的两个对象指向同一个内存地址
- 2、当我们需要将对象存入集合是,比如Map集合,需要先判断这个对象是否已经存在了,那么判断的依据是什么呢?不是equals()比较结果,而是hash值,这样判断效率较高,
- 如果发现当前对象的hash值已经存在集合中了就不会再将这个对象存在集合中,否则就存入
- 3、对象存储内存中的地址是通过hash值来确定的。
- 4、假设我们值重写了equals()方法 使得 x.equals(y)==true 旨在说明x和y是同一个对象,应当被存储在同一个内存地址。但事实并非如此:
- 没有重写hashCode()方法就更改不了hash值,就没办法使得x,y 指向同一个内存地址,也就是说,在内存中,这依然是两个不同的独立的对象!!
- 5、那么接下来,我们假设map集合中已经存放了x,我们想要向集合map中添加y,就会添加成功,因为他们的hash值并不相同,会被认为是不同的对象。这无疑是跟map集合的本意,以及程序员的本意是相违背的。
代码演示说明:
自定义两个内部类 : Student 不充写hashCode()方法以及equals()方法
Teacher两个方法都重写
可以看到:重写两个方法后,equals()方法和hashCode()的结果都指示着两个属性完全一样的对象隶属于同一个对象,是我们想要的结果。
```public class Demo02 {
static class Student{
String name;
Integer age;
public Student() {
}
public Student(String name, Integer age) {
this.name = name;
this.age = age;
}
}
static class Teacher{
String name;
Integer age;
public Teacher() {
}
public Teacher(String name, Integer age) {
this.name = name;
this.age = age;
}
//重写equals()和hashCode()
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Teacher teacher = (Teacher) o;
return Objects.equals(name, teacher.name) && Objects.equals(age, teacher.age);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
}
public static void main(String[] args) {
Student student1 = new Student("张三",12);
Student student2 = new Student("张三",12);
System.out.println("没有重写equals()方法时:"+ student1.equals(student2));//两个对象地址不相同,所以两个对象并不相等
//哈希值也不相等
System.out.println("student1的hash值:"+student1.hashCode());
System.out.println("student2的hash值:"+student2.hashCode());
//重写方法之后:预测hash值应该相同——预测结果正确
Teacher teacher1 =new Teacher("张三",12);
Teacher teacher2 =new Teacher("张三",12);
System.out.println("重写equals()方法时:"+ teacher1.equals(teacher2));//true
System.out.println("teacher1的hash值:"+teacher1.hashCode());//24022532
System.out.println("teacher2的hash值:"+teacher2.hashCode());//24022532
}
}
假如将Teacher中重写的hashCode()方法删掉:再查看两个对象的hash值:即使equals()方法判断两个对象相等,他们的hash值也不会相等。
//假如不重写 hashCode()方法
System.out.println("重写equals()方法时:"+ teacher1.equals(teacher2));//true
System.out.println("teacher1的hash值:"+teacher1.hashCode());//1078694789
System.out.println("teacher2的hash值:"+teacher2.hashCode());//1831932724