目录
一、为什么重写equals()方法时必须重写hashCode()方法
一、为什么重写equals()方法时必须重写hashCode()方法
1、关于hashCode()的约定
hashCode()方法源码注释:
If two objects are equal according to the {@code equals(Object)}
method, then calling the {@code hashCode} method on each of
the two objects must produce the same integer result.
意思就是:如果两个对象根据equals()方法比较是相等的,那么调用这两个对象的hashcode()方法也必须产生相同的结果;
2、equals()方法和hashCode()方法的关系
-
如果两个对象相同(即:用 equals 比较返回true),那么它们的 hashCode 值一定要相同;
-
如果两个对象的 hashCode 值相同,但是它们并不一定相同(即:用 equals 比较返回 false);
3、为什么一定要使用 hashcode() 方法
根本原因是为了提升程序运行效率;
hashCode()方法返回一个hashCode值,实际上就是一个int整数;
hashCode值的作用是确定该对象在哈希表中的索引位置;
根据上面equals()和hashCode()的关系,我们在比较两个对象是否相同的时候可以先比较他们的hashCode值,如果hashCode值不同的话就没有必要再使用equals()进行比较了,因为使用equals()进行比较本身就是一个低效率的过程;
举例说明:
我们都知道list集合是有序的,可以重复,set集合是无序的,不可以重复,那么怎么保证放入的元素不重复呢?仅仅使用equals()方法是不可能的,比如要存放第10001个元素,难道要与前面10000个元素挨个equals()比较吗?这效率太低了,因此hashCode就应运而生了!Java就采用了哈希表,利用哈斯算法(也叫散列算法),将对象数据根据其特征使用特定的算法将其定义到一个地址上,那么在后面存放进来的数据只需要首先判断对应的地址是否有数据,如果有就先比较它们的hashCode是否相等,如果相等就再使用equals()比较内容是否相同,反之直接插入,(同样,比较两个对象是否相同,也可以先比较两个对象的hashCode是否相等,如果相等再进行equals()比较,反之直接返回false即可)这样就大大减少了使用equals()的次数,提升了程序运行效率;
简而言之,重写hashcode()方法的目的就是:保证使用equals()方法比较相同的对象,所对应的hashCode值也相同的;
4、HashMap结构
参考文章:
复习一波HashMap底层实现原理解析https://blog.csdn.net/qq_37840993/article/details/108048597
HashMap结构:数组 + 链表(或红黑树(JDK8开始),当链表长度超过8,就会转成红黑树,以提高查询效率);
HashMap结构图:
5、重写hashcode()方法演示
代码演示:
package com.zibo.java.february.second;
public class MyEquals {
public static void main(String[] args) {
Student s1 = new Student("訾博", 24);
Student s2 = new Student("訾博", 24);
System.out.println(s1.equals(s2)); // true
System.out.println(s1.hashCode());
System.out.println(s2.hashCode());
}
}
class Student{
private String name;
private int age;
public Student() {
}
public Student(String name, Integer age) {
this.name = name;
this.age = age;
}
// 咱们来手动定制equals()方法
@Override
public boolean equals(Object o) {
// 两个对象堆内存地址相同,说明是同一个对象,自然内容也相同
if(this == o){
return true;
}
// 先判断是否是一个Student的实例对象,如果是向下转型进行比较,反之直接返回false
if(!(o instanceof Student)){
return false;
}
// 向下转型,继续判断每个值是否相等
Student student = (Student)o;
return this.name.equals(student.name) && this.age == student.age;
}
// 我这里使用idea一键重写了,具体该怎么重写hashCode()方法、有什么规则,暂不讨论
@Override
public int hashCode() {
int result = name != null ? name.hashCode() : 0;
result = 31 * result + age;
return result;
}
}
运行结果:
(如果没有重写hashCode()方法,下面两个int值是不同的,因为Object类默认实现的hashCode()方法是根据对象所存储的的堆内存地址计算出来的,既然是两个对象堆内存地址自然不同,因此hashCode不同!)
true
34671292
34671292