为什么重写equals一定要重写hashCode方法?
大家都知道,equals和hashcode是java.lang.Object类的两个重要的方法,在实际应用中常常需要重写这两个方法,但至于为什么重写这两个方法很多人都搞不明白。
下面我们看下Object类中默认的equals和hashCode方法的实现:
public boolean equals(Object obj) {
return (this == obj);
}
public native int hashCode();
以上是Object类关于这两个方法的源码,Object类默认的equals比较规则就是比较两个对象的内存地址。而hashcode是本地方法,但实际上,hashcode是根据对象的内存地址经哈希算法得来的。
import lombok.AllArgsConstructor;
import lombok.Data; /**
* Created by ganbo on 2019/6/17.
*/ @Data
@AllArgsConstructor
public class User {
private Long id;
private String name; @Override
public boolean equals(final Object o) {
if (this == o) return true;
if (!(o instanceof User)) return false;
if (super.equals(o)) return true; final User user = (User) o; if (id != null ? !id.equals(user.id) : user.id != null) return false;
return name != null ? name.equals(user.name) : user.name == null;
} @Override
public int hashCode() {
int result = 1;
result = 31 * result + (id != null ? id.hashCode() : 0);
result = 31 * result + (name != null ? name.hashCode() : 0);
return result;
} }
上面代码展示了重写equals和hashCode方法后的User类,线有如下代码:
public static void main(String[] args) {
User u1 = new User(1L, "root");
User u2 = new User(1L, "root");
System.out.println(u1.equals(u2));
System.out.println(u1.hashCode() == u2.hashCode());
}
此时u1.equals(u2)一定返回true,假如只重写equals而不重写hashCode,那么User类的hashCode方法默认就是继承父类Object的hashCode方法,由于默认的hashCode方法是根据对象的内存地址
经过hash算法得来的,显然此时u1对象和u2对象的hashCode值不一定相等,这个时候将该对象作为HashMap的key就会出现问题,跟期望的不一致(两个对象equals,却存在MashMap的两个槽上)。
然而重写了equals,且u1.equals(u2)返回true,根据hashcode的规则,两个对象相等其哈希值一定相等,所以矛盾就产生了,因此重写equals一定要重写hashcode,而且从类重写后的hashcode方法中可以看出,
重写后返回的新的哈希值与User的两个属性有关。
以下是关于hashcode的一些规定:
两个对象相等,hashcode一定相等
两个对象不等,hashcode不一定不等
hashcode相等,两个对象不一定相等
hashcode不等,两个对象一定不等
为什么重写equals一定要重写hashCode方法?的更多相关文章
- 为什么重写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方法分别是什么,和诞生的原因,当搞明白了这一点其实题目就不算是个问题了,下面我们来探讨分别探讨一 ...
- java 中为什么重写 equals 后需要重写 hashCode
本文为博主原创,未经允许不得转载: 1. equals 和 hashCode 方法之间的关系 这两个方法都是 Object 的方法,意味着 若一个对象在没有重写 这两个方法时,都会默认采用 Objec ...
- 编写高质量代码改善C#程序的157个建议——建议12: 重写Equals时也要重写GetHashCode
建议12: 重写Equals时也要重写GetHashCode 除非考虑到自定义类型会被用作基于散列的集合的键值:否则,不建议重写Equals方法,因为这会带来一系列的问题. 如果编译上一个建议中的Pe ...
- 为什么重写equals时必须重写hashCode方法?
原文地址:http://www.cnblogs.com/shenliang123/archive/2012/04/16/2452206.html 首先我们先来看下String类的源码:可以发现Stri ...
- java中为什么重写equals时必须重写hashCode方法?
在上一篇博文Java中equals和==的区别中介绍了Object类的equals方法,并且也介绍了我们可在重写equals方法,本章我们来说一下为什么重写equals方法的时候也要重写hashCod ...
- 重写equals就必须重写hashCode的原理分析
因为最近在整理Java集合的源码, 所以今天再来谈谈这个古老的话题,因为后面讲HashMap会用到这个知识点, 所以重新梳理下. 如果不被重写(原生Object)的hashCode和equals是什么 ...
随机推荐
- Codevs 3122 奶牛代理商 VIII(状压DP)
3122 奶牛代理商 VIII 时间限制: 3 s 空间限制: 256000 KB 题目等级 : 大师 Master 题目描述 Description 小徐是USACO中国区的奶牛代理商,专门出售质优 ...
- linux命令之------Linux文件系统具体目录
Linux文件系统具体目录 (1)/ Linux文件系统的入口,也是处于最高一级的目录 (2)/bin 系统所需要的那些命令处于此目录,比如Is,cp,mkdir等命令:功能和/usr/bin类似 ...
- 洛谷P3509 Frog
题目 首先分析数据范围发现m很大,所以线性做法肯定不行,因此考虑倍增,即预处理出每个点跳1次后的位置.然后只用两个数组类似于快速幂,推出每个点跳m次后的位置. 预处理离每个点第k小的点,可以用长度为k ...
- c语言博客作业03--循环结构
0.展示PTA总分 1.本章学习总结 1.1学习内容总结 循环语句 for语句: for( 表达式1; 表达式2; 表达式3 ) { // 需要执行的语句; } 其执行过程是:表达式 1 首先执行且只 ...
- Atcoder Regular Contest 060 F题第一问答案证明
一切的开始 令 \(x\) 为字符串,\(p\) 为正整数.如果对于满足 \(0\le i<|x|−p\) 的任何整数 \(i\) 满足 \(x[i]=x[i+p]\),则 \(p\) 称为 \ ...
- 利用Shell命令与HDFS进行交互
以”./bin/dfs dfs”开头的Shell命令方式 1.目录操作 在HDFS中为hadoop用户创建一个用户目录(hadoop用户) 在用户目录下创建一个input目录, HDFS的根目录下创建 ...
- IDEA实现SpringBoot热部署
1.pom.xml添加依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifac ...
- QTP测试学习笔记
QuickTest Professional(简称QTP)功能自动化测试,原属于Mercury Interactive公司产品,2006年7月被惠普公司收购了,通过安装文件目录可以看到,都是默认放在C ...
- npm install Error: EACCES: permission denied, mkdir
今天研究Electron的时候,全局安装运行 npm install electron -g时侯,报下面的错误: Error: EACCES: permission denied, mkdir '/U ...
- uboot中工具buildman的用法
1. buildman简介 uboot源码中维护的一款多线程编译测试工具 2. buildman的用法 2.1 进入uboot的源码目录 $ cd <path of uboot> 2.2 ...