为什么重写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,再将该类注解为 ...
随机推荐
- 【白话科普】10s 从零看懂 H5
最近大家有没有发现,很多微信公众号的动态内容变多了?我们常常可以看到,公众号内容中有很多动态图片甚至动画,还可以通过手指滑动切换页面,或者有一些小的点击互动. 这种看起来有点高级的小作品,其实是都是& ...
- Python中单下划线与双下划线用法总结
看mentor的脚本时,遇到self._item.callspec.getparam('')语句,理解起来比较困难,找到一篇文章,记录的比较详细,特别记录一下,以备复习. 附链接地址:http://w ...
- celery起动,运行有警告
运行命令 : celery worker -A task_log -l info: 有如下警告 2019-12-22 22:42:50,215: WARNING/MainProcess] /root ...
- Launch agent by connecting it to the master
Jenkins Node 是 Windows, Jenkins Server 在 Linux C:\JenkinsAgent\start_jenkins_agent.bat java -DSoftKi ...
- 一次性删除 .svn 文件夹
方法一 (Windows 7; Python 3.5.2) import os for (p,d,f) in os.walk(r"G:\qycache\test"): if p.f ...
- 利用python绘制分析路易斯安那州巴吞鲁日市的人口密度格局
前言 数据来源于王法辉教授的GIS和数量方法,以后有空,我会利用python来实现里面的案例,这里向王法辉教授致敬. 绘制普查人口密度格局 使用属性查询提取区边界 import numpy as np ...
- python驱动SAP完成数据导出(二)
在上一篇 python驱动SAP完成数据导出(一)中,我们提到了数据导出前,SAP布局的重要性,如何识别当前布局模式,以及如何切换到想要的布局.本篇小爬将着重讲讲数据导出的注意事项. 我们可以通过如下 ...
- system (color XX )函数详解:调整控制台颜色的命令
1.指定控制台输出的颜色属性 2.颜色属性由两个十六进制数字指定 -- 第一个为背景,第二个则为前景.每个数字可以为以下任何值之一: 例如: "COLOR fc" 在亮白色上产生亮 ...
- winform设置所有窗体统一图标
class WindowHookerManager { static WindowHooker hooker = new WindowHooker(); public static void SetA ...
- 通过CVE-2021-43297漏洞在Apache Dubbo<=2.7.13下实现RCE
目录 0 前言 1 找源头 1.1 找到触发点 1.2 可用的gadget 1.3 向上推触发点 2 构造poc 2.1 开启HttpServer 2.2 hessian2序列化过程简述 3 poc ...