博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java中为什么要重写hashCode方法和equals方法?重写了equals方法为什么还要重写hashCode方法? 啊~~终于明白了!!
阅读量:3950 次
发布时间:2019-05-24

本文共 2617 字,大约阅读时间需要 8 分钟。

在我们开发中,可能经常听到重写hashCode方法和equals方法,这是为什么呢?

为了更容易通俗易懂,来个小故事缓解一下激动的心情~~

打个比方,一个名叫张三的人去住酒店,在前台登记完名字就去了99层100号房间,此时警察来前台找叫张三的这个人住在哪间房,经过查询,该酒店住宿的有50个叫张三的,需要遍历查询,查询起来很不方便。

那么就换另外一种登记方式,前台登记时登记身份证号,警察来前台找身份证号时发现身份证号也存在重复,经过哈希算法进行计算后相同的hashcode值被分到了一个房间然后产生链表,链表查询效率非常慢,然后警察找的时候也会遇到问题。

那么只能换第三种登记方式了,前台登记时同时登记身份证号和名字,这样警察来找的时候同时按照两个条件去查,这样就能直接锁定要找的人在哪个房间。

在程序中:登记的前台好比哈希算法,名字是对比好比 equals 方法,身份证号的对比好比 hashcode 方法只有equals 和 hashcode 都满足的时候才能确保是同一个对象。

当我们重写一个类的 equals 方法时就应当连同重写 hashcode 方法,并且两个方法应满足:

1.一致性,即:当两个对象 equals 比较为 true,那么 hashcode 值应当相等,反之亦然,因为当两个对象hashcode 值相等,但是 equals 比较为 false,那么在 HashMap 中会产生链表,影响查询性能。

2.成对重写,即重写 equals 就应当重写 hashcode。

 

看完,应该心里有点东西了吧,嚯嚯~~

接着,让我们再看看,Object源码中equals方法

 

如果没有重写hashCode和equals方法,比较的是地址值,因为Object的equals方法中使用是==

因为默认的equals方法是Object的方法,比较的是内存地址;而默认的hashcode方法返回的是对象zhi的内存地址转换成的一个整数,实际上指的的也是内存,两个方法可以理解为比较的都是内存地址,这在实际开发的过程中在hashmap或者hashset里如果不重写的hashcode和equals方法的话会导致我们存对象的时候,把对象存进去了,取的时候却取不到想要的对象,这时候就需要重写这两个方法了

 

String

如果重写hashcode和equals方法,则比较的是内容

例如;两个String字符串进行比较时,比较的是内容,因为String底层重写了equals方法进行内容的比较

 

 

重写equals方法为什么还要重写hashCode方法? 

测试一:

咱们先来代码测试一下

如果只是重写了equals方法,会出现什么效果?

User类

public class User {    private Integer a;    @Override    public boolean equals(Object o) {        if (this == o) return true;        if (o == null || getClass() != o.getClass()) return false;        User user = (User) o;        return a != null ? a.equals(user.a) : user.a == null;    }

 

 

测试类:

public static void main(String[] args) {        HashMap
map = new HashMap
(); User user = new User(); user.setA(1); User user2 = new User(); user2.setA(1); map.put(user, "1"); map.put(user2, "2"); System.out.println(user.hashCode()); System.out.println(user2.hashCode()); System.out.println(map); }

 

如图: 会出现因为hash值不同而导致hashmap中存了两个对象

 

测试二:

如果同时重写hashCode方法和equals方法呢?

User类

public class User {    private Integer a;    @Override    public boolean equals(Object o) {        if (this == o) return true;        if (o == null || getClass() != o.getClass()) return false;        User user = (User) o;        return a != null ? a.equals(user.a) : user.a == null;    }    @Override    public int hashCode() {        return a != null ? a.hashCode() : 0;    }}

 

测试类:

得到只有一个结果,而不会出现两个

 

总结:

我们重写equals时,是为了用自身的方式去判断两个自定义对象是否相等,然而如果此时刚好需要我们用自定义的对象去充当hashmap的健值使用时,就会出现我们认为的同一对象,却因为hash值不同而导致hashmap中存了两个对象,从而才需要进行hashcode方法的覆盖

  • 如果两个对象equals相同,hashCode一定相同
  • 如果两个对象equals不同,hashCode不一定不同
  •        如果两个对象的hashCode相同,它们的equals并不一定相同
  •        如果两个对象的hashCode不相同,它们的equals一定相同

 

 

看完恭喜你,又知道了一点点!!!

你知道的越多,不知道的越多! 

~感谢志同道合的你阅读,  你的支持是我学习的最大动力 ! 加油 ,陌生人一起努力,共勉!!

转载地址:http://fcgwi.baihongyu.com/

你可能感兴趣的文章
c语言中关于int *p = &a 的解读
查看>>
解决Springboot2中无法访问在static/image/中的静态图片!终于解决啦
查看>>
IDEA搭建Springboot+SpringMVC+Mybatis+Mysql(详细、易懂)
查看>>
牛客网华为机试——合并表记录
查看>>
算数基本定理
查看>>
Sliding Window(POJ-2823)
查看>>
A. Greed CodeForces - 892A
查看>>
最短路 HDU - 2544
查看>>
7-12 列车厢调度(25 分)
查看>>
7-5 表达式转换(25 分)
查看>>
一个人的旅行 HDU - 2066
查看>>
浪里个浪 FZU - 2261 (多源最短路问题)
查看>>
D - Sorting It All Out POJ - 1094 (拓扑排序)
查看>>
Reward HDU - 2647 (拓扑排序)
查看>>
Divide by three, multiply by two CodeForces - 977D (拓扑排序)
查看>>
Big Event in HDU HDU - 1171 (多重背包)
查看>>
最长子序列长度 (动态规划 O(N^2))
查看>>
最长子序列长度 (贪心+二分 O( Nlog(N) ))
查看>>
数塔 HDU - 2084 (简单的dp)
查看>>
超级楼梯 HDU - 2041 ( 简单的dp )
查看>>