首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

Java中重写equals方法为什么要重写hashcode方法?

为了搞懂这个,小瑶先帮大家复习一下基本概念~然后再举个例子就可以搞懂了,~~~

hashcode epuals ==

== 与 equals的区别

如果两个引用类型变量使用==运算符,那么比较的是地址,它们分别指向的是否是同一地址的对象。结果一定是false,因为两个对象不可能存放在同一地址处。

要求是两个对象都不是能空值,与空值比较返回false。

==不能实现比较对象的值是否相同。

所有对象都有equals方法,默认是Object类的equals,其结果与==一样。

如果希望比较对象的值相同,必须重写equals方法。

hashCode与equals的区别

Object中的equals:

public boolean equals(Object obj) {

return (this == obj);

}

equals 方法要求满足:

自反性 a.equals(a)

对称性 x.equals(y)  y.equals(x)

一致性 x.equals(y)  多次调用结果一致

对于任意非空引用x,x.equals(null) 应该返回false

Object中的hashCode:

public native int hashCode();

它是一个本地方法,它的实现与本地机器有关,这里我们暂且认为他返回的是对象存储的物理位置。

当equals方法被重写时,通常有必要重写hashCode方法,以维护hashCode方法的常规约定:值相同的对象必须有相同的hashCode。

object1.equals(object2)为true,hashCode也相同;

hashCode不同时,object1.equals(object2)为false;

hashCode相同时,object1.equals(object2)不一定为true;

当我们向一个Hash结构的集合中添加某个元素,集合会首先调用hashCode方法,这样就可以直接定位它所存储的位置,若该处没有其他元素,则直接保存。若该处已经有元素存在,就调用equals方法来匹配这两个元素是否相同,相同则不存,不同则链到后面(如果是链地址法)。

先调用hashCode,唯一则存储,不唯一则再调用equals,结果相同则不再存储,结果不同则散列到其他位置。因为hashCode效率更高(仅为一个int值),比较起来更快。

HashMap#put源码

hash是key的hash值,当该hash对应的位置已有元素时会执行以下代码(hashCode相同)

if (p.hash == hash && ((k = p.key) == key || (key != null && key.equals(k))))

e = p;

如果equals返回结果相同,则值一定相同,不再存入。

如果重写equals不重写hashCode会怎样

两个值不同的对象的hashCode一定不一样,那么执行equals,结果为true,HashSet或HashMap的键会放入值相同的对象。

话不多说,直接上例子,~~~

首先我们只重写equals()方法

public class Student {

private String name;

private int age;

private String QQ;

@Override

public boolean equals(Object o) {

if (this == o) return true;

if (o == null || getClass() != o.getClass()) return false;

Student student = (Student) o;

return age == student.age &&

Objects.equals(name, student.name) &&

Objects.equals(QQ, student.QQ);

}

看我们的测试类

public class Test {

public static void main(String[] args) {

Student student = new Student();

Student student2 = new Student();

System.out.println(student.equals(student2)); //true

System.out.println(student.hashCode()); //356573597

System.out.println(student2.hashCode()); //1735600054

HashMap map = new HashMap();

map.put(student,"123");

map.put(student2,"456");

System.out.println(map.get(student));

System.out.println(map.get(student2));

}

}

依次输出

true

356573597 student 的hashcode值

1735600054 student 2的hashcode值

123

456

是否出现矛盾???

用equals比较说明对象相同,但是在HashMap中却以不同的对象存储(没有重写hascode值,两个hascode值,在他看来就是两个对象)。

到底这两个对象相等不相等????

说明必须重写hashCode()的重要性,

接下来重写重写equals方法和hashCode方法,再比较

public class Student {

private String name;

private int age;

private String QQ;

@Override

public boolean equals(Object o) {

if (this == o) return true;

if (o == null || getClass() != o.getClass()) return false;

Student student = (Student) o;

return age == student.age &&

Objects.equals(name, student.name) &&

Objects.equals(QQ, student.QQ);

}

@Override

public int hashCode() {

return Objects.hash(name, age, QQ);

}

}

测试类

public class Test {

public static void main(String[] args) {

Student student = new Student();

Student student2 = new Student();

System.out.println(student.equals(student2)); //true

System.out.println(student.hashCode()); // 29791

System.out.println(student2.hashCode()); // 29791

HashMap map = new HashMap();

map.put(student,"123");

map.put(student2,"456");

System.out.println(map.get(student)); //456

System.out.println(map.get(student2)); //456

}

}

依次输出

true

29791 //相同的对象

29791

456 //说明以一个值key存储,相同的值

456

看到这里,同学 你懂了吗?还不懂,可以自己实现一遍代码。

最后

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20200416A0DI3E00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券