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

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日

相关文章

  • Java规则引擎easy-rules详细介绍

    Java规则引擎easy-rules详细介绍 Easy Rules 是一款 Java 规则引擎,它可以让你轻松地设计和实现业务逻辑规则。它使用简单,易于理解,主要特性有: 易于使用。 你只需要定义规则和事实对象,然后把它们传递给 Easy Rules 引擎。Easy Rules 可以把规则和事实对象封装成 Rules 对象,然后应用规则。 灵活的规则模型。 …

    other 2023年6月27日
    00
  • mybatis-plus中wrapper的用法实例详解

    MyBatis-Plus中Wrapper的用法实例详解 MyBatis-Plus是一个基于MyBatis的增强工具,提供了许多便捷的功能来简化数据库操作。其中,Wrapper是MyBatis-Plus中一个重要的概念,用于构建查询条件。 1. Wrapper简介 Wrapper是MyBatis-Plus中的一个查询条件构造器,它可以帮助我们动态地构建查询条件…

    other 2023年7月28日
    00
  • Java版的7种单例模式写法示例

    下面我会为大家详细讲解“Java版的7种单例模式写法示例”的完整攻略。 标题一:什么是单例模式? 单例模式是一种常用的软件设计模式,在单例模式中,一个类只允许创建一个对象实例,所有其他对象都必须引用该对象实例。单例模式具有如下特点: 单例类只有一个实例对象。 该单例对象必须由单例类自行创建。 单例类对外提供一个访问该单例的全局访问点。 标题二:Java版的7…

    other 2023年6月27日
    00
  • 详解spring注解式参数校验

    那我来为你详细讲解“详解Spring注解式参数校验”的完整攻略。 什么是参数校验 参数校验是指对于一个方法或者函数,在调用的时候需要对输入参数进行一定的验证和校验,以确保其满足调用方的需求,防止参数错误导致的问题。 在Spring框架中,参数校验可以通过注解来完成,这个功能是由Hibernate提供的,它将JSR 303规范映射到Java中,并提供了一些注解…

    other 2023年6月27日
    00
  • Endnote怎么关闭区分大小写功能?Endnote关闭区分大小写方法

    要关闭Endnote的区分大小写功能,您可以按照以下步骤进行操作: 打开Endnote软件并选择您要关闭区分大小写功能的文档。 在菜单栏中,点击\”Edit\”(编辑)选项。 在下拉菜单中,选择\”Preferences\”(首选项)。 在弹出的首选项窗口中,选择\”Reference Types\”(参考类型)选项卡。 在参考类型列表中,选择您想要关闭区分…

    other 2023年8月16日
    00
  • C/C++中的static关键字详解

    C/C++中的static关键字详解 在C/C++中,static关键字有多种用途,它可以用于函数、变量和类。下面将详细讲解static关键字的用法和作用。 1. 静态局部变量 在函数内部声明的变量通常是自动存储期的,也就是说,它们在每次函数调用时都会被创建和销毁。但是,如果在变量声明前加上static关键字,它将成为静态局部变量,具有静态存储期。 静态局部…

    other 2023年7月29日
    00
  • jquery点击事件失效原因和解决办法

    jQuery点击事件失效原因和解决办法 在使用jQuery编写网页时,我们经常会使用点击事件来响应用户的操作。但是,有时候我们会遇到事件失效的问题。本攻略将介绍点击事件失效的原因和解决办法。 原因1:元素不存在 当我们使用jQuery绑定点击事件时,如果元素不存在,那么点击事件就会失效。以下是一个示例代码: $(document).ready(functio…

    other 2023年5月7日
    00
  • 基于springboot bean的实例化过程和属性注入过程

    下面是对“基于Spring Boot Bean的实例化过程和属性注入过程”的完整攻略: 基于Spring Boot Bean的实例化过程 Spring Boot 是一款基于 Spring Framework 的快速开发 Web 项目的工具。而在 Spring Boot 中,Bean 的实例化过程非常重要。下面是 Spring Boot Bean 的实例化过程…

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