为什么重写hashCode()和equals()方法
原创:转载需注明原创地址 https://www.cnblogs.com/fanerwei222/p/11477229.html
这两个方法可能大多数新手都没重写过,为什么要重写更是不知道了,所以这里通过一个例子就说一下重写这两个方法的作用是什么!
HashMap应该很多人都用到过, 正常情况下我都是用String类型作为key存数据的, 这种情况下:
Map<String, String> mapStr = new HashMap<>();
mapStr.put("map", "mapValue");
String value = mapStr.get("map");
System.out.println(value);
打印输出的肯定是 "mapValue"
如果key传入的是一个对象呢 ? 来看一下这种情况:
public class EqualsMain {
private String id;
public EqualsMain(String id){
this.id = id;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}public static void main(String[] args){
EqualsMain equalsMain1 = new EqualsMain("10");
EqualsMain equalsMain2 = new EqualsMain("20");
EqualsMain equalsMain3 = new EqualsMain("10");
Map<Object , String> map = new HashMap<>();
map.put(equalsMain1, "map中的数据");
System.out.println(map.get(equalsMain3));
System.out.println("----------------------");
}
}
我们传入一个EqualsMain对象
运行代码结果打印的是 : null
先不分析原因, 我们再对EqualsMain对象重写一下 hashCode()方法:
@Override
public int hashCode() {
return id.hashCode();
}
再运行一下代码:
依然是: null
我们再重写equals()方法:
@Override
public boolean equals(Object obj) {
if (null == obj) return false;
if (obj instanceof EqualsMain && this.id.equals(((EqualsMain)obj).getId())){
return true;
}else {
return false;
}
}
再运行代码:
此时会打印: "map中的数据"
贴上全部代码:
public class EqualsMain {
private String id;
public EqualsMain(String id){
this.id = id;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
@Override
public int hashCode() {
return id.hashCode();
}
@Override
public boolean equals(Object obj) {
if (null == obj) return false;
if (obj instanceof EqualsMain && this.id.equals(((EqualsMain)obj).getId())){
return true;
}else {
return false;
}
}
public static void main(String[] args){
EqualsMain equalsMain1 = new EqualsMain("10");
EqualsMain equalsMain2 = new EqualsMain("20");
EqualsMain equalsMain3 = new EqualsMain("10");
Map<Object , String> map = new HashMap<>();
map.put(equalsMain1, "map中的数据");
System.out.println(map.get(equalsMain3));
System.out.println("----------------------");
}
}
为什么会这样呢? 分析一下
进入HashMap的put方法看一下:
public V put(K key, V value) {
return putVal(hash(key), key, value, false, true);
}
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
putVal()方法太长, 贴一部分:
final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
boolean evict) {
Node<K,V>[] tab; Node<K,V> p; int n, i;
if ((tab = table) == null || (n = tab.length) == 0)
n = (tab = resize()).length;
if ((p = tab[i = (n - 1) & hash]) == null)
tab[i] = newNode(hash, key, value, null);
else {
Node<K,V> e; K k;
//此处是关键
if (p.hash == hash &&
((k = p.key) == key || (key != null && key.equals(k))))
e = p;
//省略其他代码............
方法中标记的地方是关键 !
HashMap每次put操作都会做如下判断操作:
1️⃣首先判断找到的对象的hash值是否和要传入的对象的key的hash值相等(此处体现了重写hashCode()方法的重要性);
2️⃣然后再判断传入的对象的key是否和找到的对象的key是否相等,此处用的是 == , 对象比较的是内存引用地址, 如果这里返回false的话;
3️⃣再判断一下传入的key是否equals找到的对象的key(此处体现了重写equals()方法的重要性);
如果 条件1️⃣符合且2️⃣和3️⃣中任意一个条件符合,则认定传入的对象和查找到的对象是同一个.
如果不重写hashCode(), 将调用Object的hashCode()方法,此时返回的是内存引用地址, 两个new出来的对象内存引用地址当然是不同的,所以第一次会出现null的情况;
如果不重写equals()方法, equals() 内部将调用 == 来判断两个对象是否相同,那么也是比较的对象内存引用地址, 同上, 也是null.
至此,问题就解决了.
结束
为什么重写hashCode()和equals()方法的更多相关文章
- 为什么要重写hashcode和equals方法?初级程序员在面试中很少能说清楚。
我在面试 Java初级开发的时候,经常会问:你有没有重写过hashcode方法?不少候选人直接说没写过.我就想,或许真的没写过,于是就再通过一个问题确认:你在用HashMap的时候,键(Key)部分, ...
- (转)为什么要重写 hashcode 和 equals 方法?
作者丨hsm_computer cnblogs.com/JavaArchitect/p/10474448.html 我在面试Java初级开发的时候,经常会问:你有没有重写过hashcode方法?不少候 ...
- HashMap中使用自定义类作为Key时,为何要重写HashCode和Equals方法
之前一直不是很理解为什么要重写HashCode和Equals方法,才只能作为键值存储在HashMap中.通过下文,可以一探究竟. 首先,如果我们直接用以下的Person类作为键,存入HashMap中, ...
- 为什么要重写hashcode和equals方法
我在面试 Java初级开发的时候,经常会问:你有没有重写过hashcode方法?不少候选人直接说没写过.我就想,或许真的没写过,于是就再通过一个问题确认:你在用HashMap的时候,键(Key)部分, ...
- 重写hashcode和equals方法
重写hashcode和equals方法 简乐君 2019-05-07 21:55:43 35481 收藏 191分类专栏: Java 文章标签: equals() hashcode()版权 一.前言我 ...
- 【转】 如何重写hashCode()和equals()方法
转自:http://blog.csdn.net/neosmith/article/details/17068365 hashCode()和equals()方法可以说是Java完全面向对象的一大特色.它 ...
- 如何重写hashCode()和equals()方法
hashCode()和equals()方法可以说是Java完全面向对象的一大特色.它为我们的编程提供便利的同时也带来了很多危险.这篇文章我们就讨论一下如何正解理解和使用这2个方法. 如何重写equal ...
- Java 重写 hashCode() 和 equals() 方法
1. hashCode 1.1 基本概念 hashCode 是 JDK 根据对象的地址算出来的一个 int 数字(对象的哈希码值),代表了该对象再内存中的存储位置. hashCode() 方法是超级类 ...
- 【java编程】重写HashCode和equals方法
[一]重写equals方案的规则 equals方法本来的原则 1.类的每个实例本质上都是唯一的. 2.不关心类是否提供了“逻辑相等”的测试功能 3.超类已经覆盖了equals,从超类继承过来的行为对于 ...
- Hibernate中用到联合主键的使用方法,为何要序列化,为何要重写hashcode 和 equals 方法
联合主键用Hibernate注解映射方式主要有三种: 第一.将联合主键的字段单独放在一个类中,该类需要实现java.io.Serializable接口并重写equals和hascode,再将该类注解为 ...
随机推荐
- MySQL数据操作与查询笔记 • 【第3章 DDL 和 DML】
全部章节 >>>> 本章目录 3.1 使用 DDL 定义数据库表结构 3.1.1 SQL 简介 3.1.2 维护数据库和创建数据表 3.2 使用 DDL 维护数据库表结构 ...
- 计算机系统3-> 现代计算机基石 | 图灵机理论
在理解CPU之前,我们有必要先了解一下现代计算机理论的基石--图灵机,这个抽象模型决定了现代计算机可以被实现.这个模型的工作原理也投射到了CPU的工作实现上.图灵机的知识可深可浅,换句话说,上手容易, ...
- laravel源码分析-队列Queue
laravel 源码分析具体注释见 https://github.com/FX-Max/source-analysis-laravel 前言 队列 (Queue) 是 laravel 中比较常用的一个 ...
- Linux_grep命令
搜索内容 命令格式如下 grep 参数 "搜索的内容" 搜索路径 注:搜索路径可缺省,缺省时,默认搜索当前目录以及其子目录下所有文件 显示文件名+内容: grep -r " ...
- jave 数据类型 float 的 正确赋值
1.前言 float 是单精度浮点型 ,有效数字8位 ,在机内存占4个字节 [double 是双精度浮点型 ,有效数字16位 ,在机内存占8个字节 ] 2.赋值 float a=1.3 会编译报 ...
- vert.x框架-使用spring注解功能
1.前言 习惯了spring注解风格,方便好用,现在用vert.x框架,怎么使用spring注解呢? 2.maven安装依赖包 <!--spring注解依赖包--> <depende ...
- SSM简单实现文件上传和下载
一.配置spring-mvc <!-- 配置多媒体文件解析器 --> <bean id="multipartResolver" class="org.s ...
- HDU 2041 超级楼梯 (斐波那契数列 & 简单DP)
原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=2041 题目分析:题目是真的水,不难发现规律涉及斐波那契数列,就直接上代码吧. 代码如下: #inclu ...
- HW防守 | Linux应急响应基础
最近也是拿到了启明星辰的暑期实习offer,虽然投的是安服,但主要工作是护网,昨天在公众号Timeline Sec上看到有一篇关于护网的文章,所以在这里照着人家写的在总结一下,为将来的工作打点基础. ...
- RHCSA 第七天
1.创建文件,并赋予权限611(两种方式,一种guoa,一种nnn) 2.创建目录,并赋予权限755(两种方式,一种guoa,一种nnn) 3.创建文件,并将文件的属主和属组修改其他用户 4.设置su ...