Java中 hashCode 和 equals 重写问题

214 阅读2分钟

Java中 hashCode 和 equals 重写问题

== 和equals区别 ?

== 是一种逻辑运算符,返回布尔值;

  • 两边为基本数据类型时,比较的是值;
  • 两边为对象时,比较的是对象的地址;

equals(Object obj)是Object类的一个方法,返回布尔值;

  • 只能比较对象,不能比较基本数据类型,因为equals方法的本质是Object提供的一个对象比较方法;
  • 默认其比较的是两个对象的地址,和==具有相同功能;

对象地址 和 hashCode区别 ?

com.bjpowernode.Student@15615099为对象地址,358699161为对象hashCode;

@Test
public void test01(){
    Student student=new Student();
    System.out.println(student); // com.bjpowernode.Student@15615099
    System.out.println(student.hashCode()); // 358699161
}

hashCode和equals区别 ?

Object类中的hashCode方法:

它的实现与本地机器有关,默认返回的是对象存储的物理位置的hash计算值,所以默认情况下,hashCode相等的对象 地址一定相等,即为同一对象。

public native int hashCode();

Object类中的equals方法:

默认比较的是两个对象的地址,

public boolean equals(Object obj) {
    return (this == obj);
}

为什么要重写equals ?

默认的规范往往会对equals方法进行重写,使其比较的是对象的属性值,而不是地址;

就像两个int值实现比较,我们比较的是int的值,而不关心int在内存中的物理地址,所以通常会对具有比较需求的类对象 重写equals方法。

这里的关系可以用一个Hash结构的集合的‘元素添加操作’来理解,增加一个元素时,先调用hashCode,唯一则存储,不唯一则再调用equals,结果相同则不再存储,结果不同则散列到其他位置。因为hashCode效率更高(仅为一个int值),比较起来更快。

如果不重写equals ,会出现以下情况:

两个值相同的对象,因为hashCode不一样,导致HashSet会放入值相同的对象,违背了set的初衷;

image-20210930095813758.png

重写equals时为什么要重写hashCode ?

当equals方法被重写时,通常有必要重写hashCode方法,以维护equals方法的常规约定:

值相同的对象必须有相同的hashCode

满足以下情况:
object1.equals(object2)为true,hashCode也相同;
hashCode不同时,object1.equals(object2)为false;
hashCode相同时,object1.equals(object2)不一定为true

如果只重写equals,不重写hashCode ,就会出现以下情况:

两个值不同的对象的hashCode一定不一样,那么执行equals,结果为true,HashSet会放入值相同的对象,违背了set的初衷。

image-20210930101948116.png

equals为true,但是在HashSet中却以不同的对象存储(没有重写hascode值,两个hascode值,在他看来就是两个对象)。说明必须重写hashCode()

正确重写:

image-20210930101508319.png

重写hashCode和equals后 == hashCode equals 比较:

== 判断对象地址是否相等; hashCode 获取对象hashCode; equals 判读对象值是否相等;

image-20210930153935249.png

如有错误,欢迎指正