java为什么重写equals时都推荐重写hashCode

阅读: 评论:0

java为什么重写equals时都推荐重写hashCode

java为什么重写equals时都推荐重写hashCode

很多人在重写equals时,都会看到网上一般推荐同时重写hashCode,为什么呢?一开始我以为equals中比较的是hashCode,查了下源码发现并不是这么回事,那么到底为什么会有这么一个推荐呢?

hashCode值代表的含义

首先,我们要知道hashcode值不是内存地址,hashcode值是对内存地址进行一些算法操作后得到的值,可能多个内存地址对应一个hashcode值,比如整数的取模(16%9=7,25%9=7,最后16和25具有相同的hashcode值),那为什么要对内存地址进行一些算法操作呢?这是因为到像hashMap之类的数据结构中添加数据,而hashmap中已经存有非常多的数据时,如果没有hashcode值,我们就得一个个遍历所有的数据看是否含有相同的数据,这样的效率特别低下,但当你使用hashcode值比较的话,你只需比较具有相同hashcode值的数据即可,这就使得效率大大提高;

equals()和hashCode()的区别

上面我们知道一个hashcode值可能对应多个内存地址。也就是说内存地址不同,但hash值可能相同,但hash值不同,内存地址一定不同。所以比较对象时,先通过hashCode()比较,如果不等则两对象一定不同,如果相等再通过equals()比较,如果相等则两对象相同,如果不等则两对象不同。

重写

而String重写了equals同时重写了hashCode,重写hashCode代码如下:

通过源码可以看到String类的hashCode是通过对象的值来确定的,而String类中equals比较的就是值,而不是地址。这就保证了String重写equals时equals和hashCode的一致性。
我们来看一段代码:

public static void main(String[] args) {Object o1 = new Object();Object o2 = new Object();o1 = "sss";o2 = "sss";System.out.println(o1.equals(o2));System.out.println("o1.hashCode():" + o1.hashCode());System.out.println("o2.hashCode():" + o2.hashCode());}

结果为:

我们可以看到当equals相同时,对应的hashCode也是一样的,这就是equals和hashCode的一致性。为什么会存在这种一致性呢?那是因为像hashMap,hashSet这些集合框架,当你重写了equals方法而没有重写hashCode()时,可能会出现equals相同,而hashCode却是不同的,然后在这些集合框架对hashCode比较时,显示false,这和我们的预期存在差入。

重写equals而不重写hashCode

 @Overridepublic boolean equals (Object o) {if (o instanceof Student) {Student s = (Student) o;if (this.sName.equals(s.sName)) return true;else return false;}return false;}
public static void main(String[] args) {Student s1 = new Student();Student s2 = new Student();s1.setsName("sss");s2.setsName("sss");System.out.println(s1.equals(s2));System.out.println("s1.hashCode():" + s1.hashCode());System.out.println("s2.hashCode():" + s2.hashCode());}

结果为:

从结果看没重写hashCode()时,本来我们是想两个age相同的hashCode应该是一样,可hashCode是不同的地址。而如果是hashMap或hashSet这些集合框架时,就会产生了一些错误。像hashSet去重的话,我们是想将age相同的去重,但是从上面我们知道两个age相同,但hashCode不同,而去重是对hashCode的比较,最后也就达不到我们想要的去重效果。

即重写equals又重写hashCode

@Overridepublic int hashCode () {return this.sName.hashCode();}@Overridepublic boolean equals (Object o) {if (o instanceof Student) {Student s = (Student) o;if (this.sName.equals(s.sName)) return true;else return false;}return false;}
public static void main(String[] args) {Student s1 = new Student();Student s2 = new Student();s1.setsName("sss");s2.setsName("sss");System.out.println(s1.equals(s2));System.out.println("s1.hashCode():" + s1.hashCode());System.out.println("s2.hashCode():" + s2.hashCode());}

结果为:

我们可以看到equals返回true,而且hashCode的地址也是一样的,这就符合之前所说的equals和hashCode的一致性。完美。这个时候你就没必要担心一些比较会出现问题了。所以说当你重写equals时,最好将hashCode也跟着一起重写。当然如果你非常确定你不会使用到hashCode比较,也是可以不重写hashCode的。

本文发布于:2024-02-01 10:52:06,感谢您对本站的认可!

本文链接:https://www.4u4v.net/it/170675592836106.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:重写   java   hashCode   equals
留言与评论(共有 0 条评论)
   
验证码:

Copyright ©2019-2022 Comsenz Inc.Powered by ©

网站地图1 网站地图2 网站地图3 网站地图4 网站地图5 网站地图6 网站地图7 网站地图8 网站地图9 网站地图10 网站地图11 网站地图12 网站地图13 网站地图14 网站地图15 网站地图16 网站地图17 网站地图18 网站地图19 网站地图20 网站地图21 网站地图22/a> 网站地图23