前言

最近复习,又看到了这个问题,在此记录和整理,通过例子来说明这种情况的原因,使大家可以清晰明白这个问题。

初步探索

首先我们要了解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?的更多相关文章

  1. java中为什么重写equals时必须重写hashCode方法?

    在上一篇博文Java中equals和==的区别中介绍了Object类的equals方法,并且也介绍了我们可在重写equals方法,本章我们来说一下为什么重写equals方法的时候也要重写hashCod ...

  2. java 中为什么重写 equals 后需要重写 hashCode

    本文为博主原创,未经允许不得转载: 1. equals 和 hashCode 方法之间的关系 这两个方法都是 Object 的方法,意味着 若一个对象在没有重写 这两个方法时,都会默认采用 Objec ...

  3. 为什么重写equals时必须重写hashCode方法?(转发+整理)

    为什么重写equals时必须重写hashCode方法? 原文地址:http://www.cnblogs.com/shenliang123/archive/2012/04/16/2452206.html ...

  4. 讲解:为什么重写equals时必须重写hashCode方法

    一 :string类型的==和equals的区别: 结论:"=="是判断两个字符串的内存地址是否相等,equals是比较两个字符串的值是否相等,具体就不做扩展了,有兴趣的同学可以去 ...

  5. 为什么重写equals一定要重写hashCode?

    大家都知道,equals和hashcode是java.lang.Object类的两个重要的方法,在实际应用中常常需要重写这两个方法,但至于为什么重写这两个方法很多人都搞不明白,以下是我的一些个人理解. ...

  6. 为什么重写equals后要重写hashCode

    equals和hashCode的关系 要搞清楚题目中的问题就必须搞明白equals方法和hashCode方法分别是什么,和诞生的原因,当搞明白了这一点其实题目就不算是个问题了,下面我们来探讨分别探讨一 ...

  7. 为什么重写equals一定要重写hashCode方法?

    大家都知道,equals和hashcode是java.lang.Object类的两个重要的方法,在实际应用中常常需要重写这两个方法,但至于为什么重写这两个方法很多人都搞不明白. 下面我们看下Objec ...

  8. 为什么重写 equals 方法 必须重写 hashCode

    自己学到这,就记录了下来,代码都是自己敲得,有不对的地方希望大神指点出来 为什么重写 equals 方法 必须重写 hashCode 如果你重写了equals,比如说是基于对象的内容实现的,而不重写 ...

  9. 编写高质量代码改善C#程序的157个建议——建议12: 重写Equals时也要重写GetHashCode

    建议12: 重写Equals时也要重写GetHashCode 除非考虑到自定义类型会被用作基于散列的集合的键值:否则,不建议重写Equals方法,因为这会带来一系列的问题. 如果编译上一个建议中的Pe ...

  10. [java] 为什么重写equals()必须要重写hashCode()

    本文版权归 远方的风lyh和博客园共有,欢迎转载,但须保留此段声明,并给出原文链接,谢谢合作. 在Java API文档中关于hashCode方法有以下几点规定(原文来自java深入解析一书) 1 在j ...

随机推荐

  1. centos7上Jenkins通过rpm包方式直接安装及使用war包方式升级

    一.通过rpm包方式直接安装jenkins 1.官网下载rpm安装包(前提是安装jdk) wget https://pkg.jenkins.io/redhat-stable/jenkins-2.121 ...

  2. 详解 Filter 过滤器

    1.简介 Filter也称之为过滤器,它是Servlet技术中最实用的技术,WEB开发人员通过Filter技术,对web服务器管理的所有web资源:例如Jsp, Servlet, 静态图片文件或静态 ...

  3. 烧钱时代终结!O2O还能玩啥花样?

    最终的最终,饱受亏损.烧钱玩补贴等争议的美团还是追随滴滴/快的.赶集/58的步伐,与大众点评愉快的在一起了!美团和大众点评作为O2O行业的领军企业,都因为不堪忍受持续地投入却不见回报的模式而不得不放低 ...

  4. java的23种设计模式之建造者模式

    场景和本质 场景 本质 案例 原理 应用场景 场景和本质 场景 我们要建造一个复杂的产品.比如:神州飞船,Iphone.这个复杂的产品的创建.有这样一个问题需要处理:装配这些子组件是不是有个步骤问题? ...

  5. 天哪!毫无思绪!令人感到恐惧的数学(水题?)(TOWQs)

    这道题的题目描述灰常简单,第一眼看以为是一道十分水的题目: 但是!!!(我仔细一看也没有发现这背后隐藏着可怕的真相~) 下面给出题目描述: 给出一个整数x,你可以对x进行两种操作.1.将x变成4x+3 ...

  6. MHRD_Guide

    @(Steam蒸汽动力)[MHRD|Game|How To] [CH]游戏解决方案 1.解决方案将作为完整的代码呈现,部分结决方案将有理论分析或图解. 2.根据记录板判断,解决方案远非理想. 3.慎重 ...

  7. LeetCode~报数(简单)

    报数(简单) 题目描述: 报数序列是一个整数序列,按照其中的整数的顺序进行报数,得到下一个数.其前五项如下: 1 11 21 1211 111221 1 被读作 "one 1" ( ...

  8. JavaScript中的innerHTML属性的使用

    */ * Copyright (c) 2016,烟台大学计算机与控制工程学院 * All rights reserved. * 文件名:text.html * 作者:常轩 * 微信公众号:Worldh ...

  9. 微信小程序app.js中设置公有变量

    初始化GlobalData 在App.js的最上方可以设置GlobalData的初始值. App({ globalData:{ appid: '1wqas2342dasaqwe232342xxxxxx ...

  10. FPGA小白学习之路(6)串口波特率问题的处理

    串口波特率问题的处理 此博文一共包含三个方面的内容:(1)异步串口通信的数据格式:(2)为何串口通信中接收端采样时钟频率是传输的波特率的16倍:(3)串口波特率等概念. 1.异步串口通信的数据格式 串 ...