原创:转载需注明原创地址 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()方法的更多相关文章

  1. 为什么要重写hashcode和equals方法?初级程序员在面试中很少能说清楚。

    我在面试 Java初级开发的时候,经常会问:你有没有重写过hashcode方法?不少候选人直接说没写过.我就想,或许真的没写过,于是就再通过一个问题确认:你在用HashMap的时候,键(Key)部分, ...

  2. (转)为什么要重写 hashcode 和 equals 方法?

    作者丨hsm_computer cnblogs.com/JavaArchitect/p/10474448.html 我在面试Java初级开发的时候,经常会问:你有没有重写过hashcode方法?不少候 ...

  3. HashMap中使用自定义类作为Key时,为何要重写HashCode和Equals方法

    之前一直不是很理解为什么要重写HashCode和Equals方法,才只能作为键值存储在HashMap中.通过下文,可以一探究竟. 首先,如果我们直接用以下的Person类作为键,存入HashMap中, ...

  4. 为什么要重写hashcode和equals方法

    我在面试 Java初级开发的时候,经常会问:你有没有重写过hashcode方法?不少候选人直接说没写过.我就想,或许真的没写过,于是就再通过一个问题确认:你在用HashMap的时候,键(Key)部分, ...

  5. 重写hashcode和equals方法

    重写hashcode和equals方法 简乐君 2019-05-07 21:55:43 35481 收藏 191分类专栏: Java 文章标签: equals() hashcode()版权 一.前言我 ...

  6. 【转】 如何重写hashCode()和equals()方法

    转自:http://blog.csdn.net/neosmith/article/details/17068365 hashCode()和equals()方法可以说是Java完全面向对象的一大特色.它 ...

  7. 如何重写hashCode()和equals()方法

    hashCode()和equals()方法可以说是Java完全面向对象的一大特色.它为我们的编程提供便利的同时也带来了很多危险.这篇文章我们就讨论一下如何正解理解和使用这2个方法. 如何重写equal ...

  8. Java 重写 hashCode() 和 equals() 方法

    1. hashCode 1.1 基本概念 hashCode 是 JDK 根据对象的地址算出来的一个 int 数字(对象的哈希码值),代表了该对象再内存中的存储位置. hashCode() 方法是超级类 ...

  9. 【java编程】重写HashCode和equals方法

    [一]重写equals方案的规则 equals方法本来的原则 1.类的每个实例本质上都是唯一的. 2.不关心类是否提供了“逻辑相等”的测试功能 3.超类已经覆盖了equals,从超类继承过来的行为对于 ...

  10. Hibernate中用到联合主键的使用方法,为何要序列化,为何要重写hashcode 和 equals 方法

    联合主键用Hibernate注解映射方式主要有三种: 第一.将联合主键的字段单独放在一个类中,该类需要实现java.io.Serializable接口并重写equals和hascode,再将该类注解为 ...

随机推荐

  1. 万能密码:‘or 1=1-- 实战SQL注入,秒破后台

    主要是没有对登录密码的字符串进行参数化和过滤,所以导致网站可以直接用"万能密码"进行突破登录 仅供学习交流 这是某同学做的网站,今天无聊打开了,并帮他进行测试一下 看到这个后台,感 ...

  2. Shell自动上传下载文件到SFTP服务器

    1.说明 本文提供一个Shell脚本, 可以自动连接到SFTP服务器, 然后上传或者下载指定的文件, 进而可以使用Linux的corntab命令, 定时执行脚本上传下载文件, 实现文件的同步或者备份功 ...

  3. idea 创建Maven项目,Enable auto Import报“本地服务器没有从权威服务器上收到响应”

    完整的报错信息:Could not transfer artifact org.apache.maven.plugins:maven-clean-plugin:pom:2.5 from/to cent ...

  4. JMeter_实现算法加密

    JMeter有两种方法可以实现算法加密 一.使用__digest自带函数      参数说明: Digest algorithm:算法摘要,可输入值:MD2.MD5.SHA-1.SHA-224.SHA ...

  5. win10 安装vue 详解-包括node.js、npm、webpack

    1.下载 去官网下载 node.js https://nodejs.org/en/download/ 一般不会选择最新的,我安装的是 12.18.4 进入历史记录页面网址 https://nodejs ...

  6. xml文件 加载properties文件的两种方法与注意事项

    1.遇到的问题: 配置redisSpringContext.xml 时,遇到 properties加载失败,提示BeanDefinitionStoreException  和   java.lang. ...

  7. VUE3 之 全局组件与局部组件

    1. 概述 老话说的好:忍耐是一种策略,同时也是一种性格磨炼. 言归正传,今天我们来聊聊 VUE 的全局组件与局部组件. 2. 全局组件 2.1 不使用组件的写法  <body> < ...

  8. 发现一个现象:golang中大量的go出新协程,必然在GC统计中出现1ms以上的GC延迟

    结论:协程池还是有必要的,能够有效减小GC的压力. 我的某个服务,为了方(tou)便(lan),一些异步处理的场合直接go出协程来处理. 服务中使用这样的代码来统计GC的延迟: var mem run ...

  9. golang中的标准库数据格式

    数据格式介绍 是系统中数据交互不可缺少的内容 这里主要介绍JSON.XML.MSGPack JSON json是完全独立于语言的文本格式,是k-v的形式 name:zs 应用场景:前后端交互,系统间数 ...

  10. 【webpack4.0】---webpack的基本使用(三)

    一.webpack-dev-server 1.安装 cnpm   install  webpack-dev-server  -D 2.作用 开启一个web服务,监听文件的变化并自动刷新网页,做到实时预 ...