Java 中HashCode作用_动力节点Java学院整理

yizhihongxing

Java 中HashCode作用

概述

hashCode() 是 Java 中在 Object 类下的一个方法,其主要目的是返回对象的哈希码。哈希码可以看做是一个对象的特征码,不同的对象拥有不同的哈希码,哈希码值是根据对象内容计算而得的 32 位整数。

在 Java 中,哈希码在很多场合都有很重要的作用,例如:

  • HashMap、HashSet、Hashtable、WeakHashMap、IdentityHashMap 等数据结构都使用哈希码来确定对象在集合内的位置;
  • 当一个对象要被序列化成字节序列时,先计算出对象的哈希码,然后将其写入输出流;
  • 当一个对象被作为参数传递给具有 hashCode 参数的算法时,算法可以根据哈希码来优化计算;
  • 等等。

在实际编程中,我们有时需要重写对象的 hashCode() 方法,这是因为对于不同的类需要不同的哈希码策略。在接下来的段落中,我们将通过示例来说明哈希码的应用和编写过程。

示例1:使用哈希码定位对象

HashMap 是 Java 中最常使用的 Map 结构,其内部实现是一个键值对列表,查询的时候使用键的哈希值和散列函数来快速定位对象。下面我们将演示存储自定义对象时,必须重写该对象的 hashCode() 方法,否则在 HashMap 内检索该对象将会失败。

public class Student {
    private int id;
    private String name;

    public Student(int id, String name) {
        this.id = id;
        this.name = name;
    }

    @Override
    public int hashCode() {
        return Objects.hash(id, name);
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null || getClass() != obj.getClass()) return false;
        Student student = (Student) obj;
        return id == student.id && Objects.equals(name, student.name);
    }
}

public class Main {
    public static void main(String[] args) {
        Map<Student, String> map = new HashMap<>();
        map.put(new Student(1, "Tom"), "A");
        map.put(new Student(2, "Mary"), "B");
        map.put(new Student(3, "Mathew"), "C");
        System.out.println(map.get(new Student(1, "Tom"))); // 正常输出:A
        System.out.println(map.get(new Student(3, "Mathew"))); // 正常输出:C
        System.out.println(map.get(new Student(1, "Jerry"))); // 失败输出:null
    }
}

可以看到,由于哈希码被正确地重写了,我们可以成功地定位到 Map 内存储的元素,而在没有重写哈希码的情况下,虽然对象的内容相同,但是由于哈希码不同,因此会被判断为不同的对象,查询结果自然也会失败。

示例2:使用哈希码序列化和反序列化对象

使用哈希码可以方便地序列化和反序列化对象,下面我们将演示自定义类的哈希码实现以及使用哈希码序列化和反序列化对象。

public class Student implements Serializable {
    private static final long serialVersionUID = 1L;
    private int id;
    private String name;

    public Student(int id, String name) {
        this.id = id;
        this.name = name;
    }

    @Override
    public int hashCode() {
        return Objects.hash(id, name);
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null || getClass() != obj.getClass()) return false;
        Student student = (Student) obj;
        return id == student.id && Objects.equals(name, student.name);
    }
}

public class Main {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        Student student = new Student(1, "Tom");
        System.out.println(student.hashCode()); // 正常输出:88431941

        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(baos);
        oos.writeObject(student);
        oos.flush();
        byte[] bytes = baos.toByteArray();
        oos.close();
        baos.close();

        ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
        ObjectInputStream ois = new ObjectInputStream(bais);
        Student s2 = (Student) ois.readObject();
        ois.close();
        bais.close();

        System.out.println(s2.hashCode()); // 正常输出:88431941
        System.out.println(s2.equals(student)); // 正常输出:true
    }
}

可以看到,我们通过实现自定义的 hashCode() 方法,可以成功地序列化和反序列化对象,这是因为哈希码作为一个对象的重要特征,其内容被写入到字节序列中,成功地标识该对象。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java 中HashCode作用_动力节点Java学院整理 - Python技术站

(0)
上一篇 2023年6月27日
下一篇 2023年6月27日

相关文章

  • 关于JS 预解释的相关理解

    关于JS 预解释的相关理解 在JavaScript中,预解释(Hoisting)是指在代码执行之前,JavaScript引擎会将变量和函数的声明提升到当前作用域的顶部。这意味着在代码中,我们可以在声明之前使用这些变量和函数。 变量的预解释 当JavaScript引擎遇到变量声明时,会将变量声明提升到当前作用域的顶部。但是,只有变量的声明会被提升,而不是赋值。…

    other 2023年7月29日
    00
  • msixbundle怎么打开?win10后缀.MSIX安装包怎么安装使用?

    MSIXBundle的打开和安装使用攻略 MSIXBundle是一种用于打包和分发Windows应用程序的文件格式。它可以包含一个或多个MSIX安装包,以及其他相关资源。下面是详细的攻略,教你如何打开和安装使用MSIXBundle文件。 打开MSIXBundle文件 要打开MSIXBundle文件,按照以下步骤进行操作: 首先,确保你的计算机上已经安装了Wi…

    other 2023年8月5日
    00
  • 苹果iOS 9.3.2 Beta 4开发者预览版发布:修复白屏崩溃等bug

    苹果iOS 9.3.2 Beta 4开发者预览版发布 苹果iOS 9.3.2 Beta 4开发者预览版已经发布,该版本解决了许多已知的bug,并在提高性能方面进行了一些改进。此次更新的重点是修复一些用户反馈比较强烈的问题,特别是白屏崩溃等问题。该版本计划在近期正式发布,对于开发人员和测试人员来说,这将是一个非常有用的版本。 如何升级到iOS 9.3.2 Be…

    other 2023年6月26日
    00
  • C语言递归思想实现汉诺塔详解

    C语言递归思想实现汉诺塔详解 什么是汉诺塔问题? 汉诺塔问题是一个古老的数学谜题,也是递归思想的典型应用。问题由以下三个规则定义: 有三根杆子,第一根杆子上有若干个直径大小不一的圆盘,第二根杆子上一个圆盘没有,第三根杆子上一个圆盘没有。 每次只能移动一个盘子。 大盘子不能放在小盘子上面。 目标是从初始状态移动所有圆盘到最后一根杆子上。我们可以用 A、B、C …

    other 2023年6月27日
    00
  • spring boot整合CAS配置详解

    下面为你讲解“Spring Boot整合CAS配置详解”。 1. 前置知识 在开始讲解之前需要了解的几个概念: CAS(Central Authentication Service,中心认证服务):是 Yale 大学发起的一个企业级的、开源的、单点登录系统。 Spring Boot:是一个基于 Spring 框架实现的、简化了配置的快速开发框架。 Thyme…

    other 2023年6月25日
    00
  • “内存不足”问题的处理办法

    处理“内存不足”问题的完整攻略 1. 了解“内存不足”问题的原因 在处理“内存不足”问题之前,首先需要了解造成该问题的原因。常见的原因包括:- 运行过多的程序或进程,消耗了系统的内存资源。- 单个程序或进程占用了过多的内存。- 内存泄漏,导致内存资源无法释放。 2. 监控内存使用情况 在处理“内存不足”问题之前,需要先了解当前系统的内存使用情况。可以通过以下…

    other 2023年7月31日
    00
  • 192.168.1.1或192.168.0.1路由器常用密码小结

    192.168.1.1或192.168.0.1路由器常用密码小结 什么是192.168.1.1和192.168.0.1 在局域网中,为了让多个设备能够互相通信,需要使用路由器来进行网络连接。路由器通常会有一个默认的IP地址作为登录地址,常见的包括192.168.1.1和192.168.0.1两个地址。 如何登录路由器 使用路由器的管理界面需要登录路由器。当输…

    other 2023年6月27日
    00
  • iso/iec14443协议浅谈

    iso/iec14443协议浅谈 ISO/IEC 14443是一种近场通信(NFC)协议,用于智能卡和读卡器之间的通信。本文将提供一个完整的攻略,包括协议概述、通信过程、示例说明等。 1. 协议概述 ISO/IEC 14443协议定义了智能卡和读卡器之间的物理层和数据链路层通信规范。该议使用13.56MHz的无线电频率进行通信,支持两种通信式:主动模式和被动…

    other 2023年5月8日
    00
合作推广
合作推广
分享本页
返回顶部