java 为什么重写equals一定要重写hashcode?
前言
最近复习,又看到了这个问题,在此记录和整理,通过例子来说明这种情况的原因,使大家可以清晰明白这个问题。
初步探索
首先我们要了解equals方法是什么,hashcode方法是什么。
equals方法
equals 是java的obejct类的一个方法,equals的源码如下:
public boolean equals(Object paramObject){
return(this == paramObject);
}
由此我们可以看到equals是用来比较两个对象的内存地址是否相等。
hashCode方法
hashCode方法是本地方法,用于计算出对象的一个散列值,用于判断在集合中对象是否重复的关键。
一条定理
equals相同的对象,hashCode必然相同。
代码示例
建立一个Student类。
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);
}
}
在 student 类中,我们重写了equals方法。
书写一个测试类
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<Student, String> 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 相等的对象,hashcode却不相等,同时在map中用不同的对象进行了存储,map计算出来的hash值不同,但equals却相同。这时候懵了。到底两个对象一样不一样呢。
所以我们在重写equals的时候,必须重写hashcode。
重新定义 student 类
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<Student, String> 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
几条定理
1、两个对象的equals相等,hashcode必然相等。
2、两个对象不等,hashcode也可能相等。
3、hashcode相等,对象不一定相等。
4、hashcode不等,对象一定不等。
java 为什么重写equals一定要重写hashcode?的更多相关文章
- java中为什么重写equals时必须重写hashCode方法?
在上一篇博文Java中equals和==的区别中介绍了Object类的equals方法,并且也介绍了我们可在重写equals方法,本章我们来说一下为什么重写equals方法的时候也要重写hashCod ...
- java 中为什么重写 equals 后需要重写 hashCode
本文为博主原创,未经允许不得转载: 1. equals 和 hashCode 方法之间的关系 这两个方法都是 Object 的方法,意味着 若一个对象在没有重写 这两个方法时,都会默认采用 Objec ...
- 为什么重写equals时必须重写hashCode方法?(转发+整理)
为什么重写equals时必须重写hashCode方法? 原文地址:http://www.cnblogs.com/shenliang123/archive/2012/04/16/2452206.html ...
- 讲解:为什么重写equals时必须重写hashCode方法
一 :string类型的==和equals的区别: 结论:"=="是判断两个字符串的内存地址是否相等,equals是比较两个字符串的值是否相等,具体就不做扩展了,有兴趣的同学可以去 ...
- 为什么重写equals一定要重写hashCode?
大家都知道,equals和hashcode是java.lang.Object类的两个重要的方法,在实际应用中常常需要重写这两个方法,但至于为什么重写这两个方法很多人都搞不明白,以下是我的一些个人理解. ...
- 为什么重写equals后要重写hashCode
equals和hashCode的关系 要搞清楚题目中的问题就必须搞明白equals方法和hashCode方法分别是什么,和诞生的原因,当搞明白了这一点其实题目就不算是个问题了,下面我们来探讨分别探讨一 ...
- 为什么重写equals一定要重写hashCode方法?
大家都知道,equals和hashcode是java.lang.Object类的两个重要的方法,在实际应用中常常需要重写这两个方法,但至于为什么重写这两个方法很多人都搞不明白. 下面我们看下Objec ...
- 为什么重写 equals 方法 必须重写 hashCode
自己学到这,就记录了下来,代码都是自己敲得,有不对的地方希望大神指点出来 为什么重写 equals 方法 必须重写 hashCode 如果你重写了equals,比如说是基于对象的内容实现的,而不重写 ...
- 编写高质量代码改善C#程序的157个建议——建议12: 重写Equals时也要重写GetHashCode
建议12: 重写Equals时也要重写GetHashCode 除非考虑到自定义类型会被用作基于散列的集合的键值:否则,不建议重写Equals方法,因为这会带来一系列的问题. 如果编译上一个建议中的Pe ...
- [java] 为什么重写equals()必须要重写hashCode()
本文版权归 远方的风lyh和博客园共有,欢迎转载,但须保留此段声明,并给出原文链接,谢谢合作. 在Java API文档中关于hashCode方法有以下几点规定(原文来自java深入解析一书) 1 在j ...
随机推荐
- Swift 浅谈Struct与Class
讨论Struct与Class之前,我们先来看一个概念:Value Type(值类型),Reference Type(引用类型): 1. 值类型的变量直接包含他们的数据,对于值类型都有他们自己的数据副本 ...
- C++走向远洋——27(项目三,时间类)
*/ * Copyright (c) 2016,烟台大学计算机与控制工程学院 * All rights reserved. * 文件名:time.cpp * 作者:常轩 * 微信公众号:Worldhe ...
- sublime 安装Anaconda插件 配置python开发环境
我的sublime 3 python 3.6.6 安装Anaconda插件 由于Anaconda插件本身无法知道Python安装的路径,所以需要设置Python主程序的实际位置.选择Settings ...
- 将mysql数据库集成到idea中
将mysql数据库集成到idea中
- Java工作流引擎结合可视化表单开发,10分钟完成一个业务流程发布
回忆以前工作流引擎的应用,感觉历历在目啊!当初公司接了一个项目关于政府单位公文流转的管理系统,一开始客户跟我画了十多张业务流程图.话说这十多张业务流程图,涉及的业务范围还蛮多,像用审批授权,开通流程, ...
- 压力测试(四)-Mysql数据库压测实操
1.Jmeter压测实战之JDBC request压测Mysql讲解 简介:讲解jdbc压测mysql相关准备工作,jar包添加,配置讲解 1.Thread Group -> add -> ...
- go语言指南之切片练习
题目: 实现 Pic.它应当返回一个长度为 dy 的切片,其中每个元素是一个长度为 dx,元素类型为 uint8 的切片.当你运行此程序时,它会将每个整数解释为灰度值(好吧,其实是蓝度值)并显示它所对 ...
- PHP网络爬虫实践:抓取百度搜索结果,并分析数据结构
百度的搜索引擎有反爬虫机制,我先直接用guzzle试试水.代码如下: <?php /** * Created by Benjiemin * Date: 2020/3/5 * Time: 14:5 ...
- http协议概览
这里我只是对一些知识进行简单的整理,方便自己理解记忆,还有很多不完善的地方,更多细节,需要查看书籍或者其他文章 http协议的发展过程 HTTP 是基于 TCP/IP 协议的应用层协议.它不涉及数据包 ...
- 前端每日实战:17# 视频演示如何用纯 CSS 创作炫酷的同心矩形旋转动画
效果预览 按下右侧的"点击预览"按钮可以在当前页面预览,点击链接可以全屏预览. https://codepen.io/comehope/pen/bMvbRp 可交互视频教程 此视频 ...