iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > Python >Java基础之浅谈hashCode()和equals()
  • 151
分享到

Java基础之浅谈hashCode()和equals()

2024-04-02 19:04:59 151人浏览 八月长安

Python 官方文档:入门教程 => 点击学习

摘要

写在前面 其实很早我就注意到阿里巴巴Java开发规范有一句话:只要重写 equals,就必须重写 hashCode。 我想很多人都会问为什么,所谓知其然知其所以然,对待知识不单止知

写在前面

其实很早我就注意到阿里巴巴Java开发规范有一句话:只要重写 equals,就必须重写 hashCode

我想很多人都会问为什么,所谓知其然知其所以然,对待知识不单止知道结论还得知道原因。

hashCode方法

hashCode()方法的作用是获取哈希码,返回的是一个int整数

学过数据结构的都知道,哈希码的作用是确定对象在哈希表的索引下标。比如HashSet和HashMap就是使用了hashCode方法确定索引下标。如果两个对象返回的hashCode相同,就被称为“哈希冲突”。

equals方法

equals()方法的作用很简单,就是判断两个对象是否相等,equals()方法是定义在Object类中,而所有的类的父类都是Object,所以如果不重写equals方法则会调用Object类的equals方法。

Object类的equals方法是用“”号进行比较,在很多时候,因为号比较的是两个对象的内存地址而不是实际的值,所以不是很符合业务要求。所以很多时候我们需要重写equals方法,去比较对象中每一个成员变量的值是否相等。

问题来了

重写equals()方法就可以比较两个对象是否相等,为什么还要重写hashcode()方法呢?

因为HashSet、HashMap底层在添加元素时,会先判断对象的hashCode是否相等,如果hashCode相等才会用equals()方法比较是否相等。换句话说,HashSet和HashMap在判断两个元素是否相等时,会先判断hashCode,如果两个对象的hashCode不同则必定不相等

下面我们做一个试验,有一个User类,只重写equals()方法,然后放到Set集合中去重。


public class User {

    private String id;

    private String name;

    private Integer age;
    
    public User(String id, String name, Integer age) {
        this.id = id;
        this.name = name;
        this.age = age;
    }
    
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        User user = (User) o;
        return Objects.equals(id, user.id) &&
            Objects.equals(name, user.name) &&
            Objects.equals(age, user.age);
    }
    
    //getter、setter、toString方法
}

然后我们循环创建10个成员变量的值都是一样的User对象,最后放到Set集合中去重。


public static void main(String[] args) {
    List<User> list = new ArrayList<>();
    for (int i = 0; i < 10; i++) {
        User user = new User("1", "张三", 18);
        list.add(user);
    }
    Set<User> set = new HashSet<>(list);
    for (User user : set) {
        System.out.println(user);
    }
    List<User> users = list.stream().distinct().collect(Collectors.toList());
    System.out.println(users);
}

按道理我们预期会去重,只剩下一个“张三”的user,但实际上因为没有重写hashCode方法,所以没有去重。

接着我们在User类里面重写一些hashCode方法再试试,其他不变。


public class User {
    //其他不变
    
    //重写hashCode方法
    @Override
    public int hashCode() {
        return Objects.hash(id, name, age);
    }
}

再运行,结果正确。

究其原因在于HashSet会先判断hashCode是否相等,如果hashCode不相等就直接认为两个对象不相等,不会再用equals()比较了。我们不妨看看重写hashCode方法和不重写hashCode方法的哈希码。

这是不重写hashCode方法的情况,每个user对象的哈希码都不一样,所以HashSet会认为都不相等。

这是重写hashCode方法的情况,因为是用对象所有的成员变量的值计算出的哈希码,所以只要两个对象的成员变量都是相等的,则生成的哈希码是相同的。

那么有些人看到这里,就会问,如果两个对象返回的哈希码都是一样的话,是不是就一定相等

答案是不一定的,因为HashSet、HashMap判断哈希码相等后还会再用equals()方法判断。

总而言之:

  • 哈希码不相等,则两个对象一定不相同。
  • 哈希码相等,两个对象不一定相同。
  • 两个对象相同,则哈希码和值都一定相等。

总结

所以回到开头讲的那句,只要重写 equals,就必须重写 hashCode,这是一个很重要的细节,如果不注意的话,很容易发生业务上的错误。

特别是有时候我们明明用了HashSet,distinct()去重,但是就是不生效,这时应该回头看看重写了equals()和hashCode()方法了吗?

到此这篇关于Java基础之浅谈hashCode()和equals()的文章就介绍到这了,更多相关hashCode()和equals()内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: Java基础之浅谈hashCode()和equals()

本文链接: https://www.lsjlt.com/news/128647.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Java基础之浅谈hashCode()和equals()
    写在前面 其实很早我就注意到阿里巴巴Java开发规范有一句话:只要重写 equals,就必须重写 hashCode。 我想很多人都会问为什么,所谓知其然知其所以然,对待知识不单止知...
    99+
    2022-11-12
  • 浅谈Java基础知识之BigDecimal
    目录一、基本使用二、舍入模式三、注意事项四、异常处理 ArithmeticException异常一、基本使用 使用示例: // 初始化 BigDecimal bd1=new Bi...
    99+
    2022-11-12
  • 浅谈java中为什么重写equals后需要重写hashCode
    目录一、先看现象二、为什么要重写hashCode三、实现代码四、总结一、先看现象 public class TestDemo { public static void ...
    99+
    2022-11-12
  • 浅谈Python基础之I/O模型
    一、I/O模型 IO在计算机中指Input/Output,也就是输入和输出。由于程序和运行时数据是在内存中驻留,由CPU这个超快的计算核心来执行,涉及到数据交换的地方,通常是磁盘、网络等,就需要IO接口。 ...
    99+
    2022-06-04
    浅谈 模型 基础
  • 浅谈java Properties类的使用基础
    Properties类继承自HashTable,通常和io流结合使用。它最突出的特点是将key/value作为配置属性写入到配置文件中以实现配置持久化,或从配置文件中读取这些属性。它的这些配置文件的规范后缀名为".properties"。表...
    99+
    2023-05-30
  • 浅谈Python基础之列表那些事儿
    一、列表的格式 二、列表的相关操作("增"、"删"、"改",“查”) <1> 添加元素 append()通过append可以向列表添加元素。 例: 运行结果: <2> 修改元素("改")...
    99+
    2022-06-02
    Python列表操作 python list列表
  • 浅谈java网络编程基础知识
    这篇文章主要浅谈java网络编程基础知识,内容简而易懂,希望大家可以学习一下,学习完之后肯定会有收获的,下面让小编带大家一起来看看吧。网络基础知识1、OSI分层模型和TCP/IP分层模型的对应关系这里对于7层模型不展开来讲,只选择跟这次系列...
    99+
    2023-05-30
    java ava
  • 浅谈Java基准性能测试之JMH
    目录一、JMH vs JMeter二、JMH基本用法2.1、创建JMH项目2.2、编写基准测试代码2.3、JMH打包、运行2.4、JMH与Springboot三、JMH注解3.1、J...
    99+
    2022-11-12
  • Java基础之super关键字浅析
    目录一、定义二、应用2.1    应用范围2.2    用法2.2.1    在子类中调用父类的属性或方法2.2.2 &n...
    99+
    2022-11-13
  • Java基础之FileInputStream和FileOutputStream流详解
    目录一、前言二、创建流对象三、FileInputStream常用方法四、FileOutputStream常用方法五、输入输出流测试代码一、前言 FileInputStream 用于读...
    99+
    2022-11-12
  • Java基础知识之成员变量和局部变量浅显易懂总结
    目录引言java变量分类JVM中的主要内存空间三大变量内存分配情况三区介绍栈区堆区方法区基本介绍成员变量局部变量变量使用总结引言 成员变量和局部变量在每种编程语言中都有涉及,如果之前...
    99+
    2022-11-12
  • Java基础之文件和目录操作
    目录一、前言二、构造方法三、文件元数据四、文件操作五、目录操作六、总结一、前言 文件和目录操作最终是与操作系统和文件系统相关的,不同系统的 实现是不一样的,但Java中的java.i...
    99+
    2022-11-12
  • java 基础之final、finally和finalize的区别
    java 基础之final、finally和finalize的区别final可以修饰类,不能被继承;可以修饰方法,不能被重写;可以修饰变量,只能赋值一次。finally是try语句中的语句体,不能单独使用,用来释放资源;finalize是一...
    99+
    2023-05-31
    final finally finalize
  • Java基础学习之实参和形参
    目录关于变量的赋值: 如果变量是基本数据类型,此时赋值的是变量所保存的数据值。 如果变量是引用数据类型,此时赋值的是变量所保存的数据的地址值。 public class Va...
    99+
    2022-11-12
  • 一文带你了解JavaScript基础之深拷贝和浅拷贝
    目录浅拷贝深拷贝补充总结拷贝(又名克隆,复制等),但是又分深拷贝和钱拷贝。 其实这个问题有时候想通了就很简单,如果想不通可能会有点绕,不过其难度比闭包等好理解的多。 为什么又这个概念...
    99+
    2022-11-12
  • Java基础之Math和Random类知识总结
    java的Math类 java中的java.lang.Math类可以直接使用,不需要导包,在JDK的API 中看到Math类被final修饰着,那么说明了这个Math类不能被继承,...
    99+
    2022-11-12
  • Java 基础语法之解析 Java 的包和继承
    目录一、包1. 概念2. 使用方式3. 静态导入4. 创建包5. 包的访问权限6. 常见的系统包二、继承1. 概念2. 语法规则(含 super 使用)3. protected 关键...
    99+
    2022-11-12
  • 零基础学Java之什么是对象和类
    这篇文章主要讲解了“零基础学Java之什么是对象和类”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“零基础学Java之什么是对象和类”吧!01、面向过程和面向对象三妹是不是要问,什么是 OOP...
    99+
    2023-06-15
  • JAVA基础类库之String类,StringBuffer类和StringBuilder类
    目录引言String类String类构造方法 String常用方法:简单介绍的方法详细介绍的方法StringBuffer/StringBuilder常用方法StringBu...
    99+
    2022-11-12
  • Java基础之Bean的创建、定位和使用
    目录一、前言二、自动装配Bean2.1 注册Bean2.2 使用Bean三、手动装配3.1 Java类四、XML文件五、导入配置5.1 Java类六、导入到XML一、前言 Bean是...
    99+
    2022-11-12
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作