Java面试题 -- 为什么重写equals就一定要重写hashcode方法

news2024/11/15 11:05:56

在回答这个问题之前我们先要了解equals与hascode方法的本质是做什么的

1. equals方法

public boolean equals(Object obj) {
        return (this == obj);
    }

我们可以看到equals在不重写的情况下是使用==判断地址值是否相同

所以默认的 equals 的逻辑就是判断的双方是否引用了一个对象,如果是那就是相等的,如果不是那就不相等。

默认的 equals 看似能满足我们的要求,但有些情况下却不能。在开发过程中,我们更希望比较的是两个对象的内容是否相等

package com.Month08.Day_02;

import java.util.Objects;

public class Person {
    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public Person() {
    }
}
package com.Month08.Day_02;

import java.util.stream.Stream;

public class Test {
    public static void main(String[] args) {
        Person a = new Person("a",4);
        Person b = new Person("a", 4);
        System.out.println(a.equals(b));
    }
}

在这里插入图片描述

可以看到在这里我们传入相同的值的情况下得到的结果却是false

2. HashCode

简而言之hashcode是通过将内部存储地址映射成一个整型值,这个整型值就是hashcode

默认情况下,hashCode()方法返回的是对象的内存地址的哈希码表示。

public int hashCode() {
        int h = hash;
        if (h == 0 && !hashIsZero) {
            h = isLatin1() ? StringLatin1.hashCode(value)
                           : StringUTF16.hashCode(value);
            if (h == 0) {
                hashIsZero = true;
            } else {
                hash = h;
            }
        }
        return h;
    }

3. 什么是散列表

在Java中,散列表(Hash Table)是一种非常重要的数据结构,它通过哈希函数(Hash Function)将输入(通常是键Key)映射到表中一个位置来访问记录,以加快查找的速度。散列表通常是以数组的形式实现的,但不同于普通的数组,散列表中的每个槽位(slot)并不直接存储数据,而是存储数据的索引(或称为指针),这个索引指向实际存储数据的位置。这种设计使得数据的查找、插入和删除操作都非常快

  • HashMap:这是Java中最常用的类之一,它实现了Map接口,是一个基于哈希表的Map接口的非同步实现。HashMap允许使用null值和null键,不保证映射的顺序;特别是它不保证该顺序随时间的推移保持不变。
  • Hashtable:虽然名为Hashtable,但它实际上也是一个散列表的实现。不过,与HashMap相比,Hashtable是同步的,这意味着它在多线程环境下是安全的。但是,由于同步操作带来的开销,Hashtable在单线程环境下的性能通常低于HashMap。另外,Hashtable不允许键或值为null。
  • LinkedHashMap:这个类扩展了HashMap,并维护了一个运行于所有条目的双重链接列表。这个链表定义了迭代器遍历条目的顺序,该顺序可以是插入顺序或者是访问顺序(取决于构造器中的accessOrder参数)。
  • TreeMap:虽然TreeMap不是基于哈希表的,但它实现了Map接口,并且可以看作是一种有序的映射(基于红黑树实现)。这里提到它是因为它在某些方面与HashMap等散列表实现有对比意义。

3. 只重写equals会导致什么问题?

在这个Person类中我们只重写了equals方法

package com.Month08.Day_02;

import java.util.Objects;

public class Person {
    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public Person() {
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Person person = (Person) o;
        return age == person.age && Objects.equals(name, person.name);
    }


}

如何我们在测试类中new两个对象 , 因为此时的euqals方法已经被重写 , 尽管对象a , b的地址值不同但是因为都是空参 , 也就是传入的值相同会使得a.equals(b)为true , 但是优惠遇到一个问题也就是HashCode值不相同

package com.Month08.Day_02;

import java.util.stream.Stream;

public class Test {
    public static void main(String[] args) {
        Person a = new Person();
        Person b = new Person();
        System.out.println(a); // com.Month08.Day_02.Person@214c265e
        System.out.println(b); // com.Month08.Day_02.Person@448139f0
        System.out.println(a.hashCode()); // 558638686
        System.out.println(b.hashCode()); // 1149319664
        System.out.println(a.equals(b)); // true
    }
}

我们知道在散列表中如hashmap中 , 在储存元素之前会通过计算key的值来确定key是否重复 , 那么回到上面的问题 , 如果 我们将a , b这两个对象作为key进行储存 , 通过HashCode计算发现他们HashCode不相同 , 那么这两个对象到底是相同的还是不同的呢?

 HashMap<Person, String> map = new HashMap<>();
        map.put(a , "123");
        map.put(b , "456");
        System.out.println(map.get(a)); //123
        System.out.println(map.get(b)); // 456

所以为了避免这样的问题 , 我们在重写equals的时候同时需要重新hashcode

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1975890.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【EI会议征稿】第四届高性能计算与通信工程国际学术会议(HPCCE 2024)

出版出版 【SPIE出版 | 往届会后3个月内完成EI检索】 第四届高性能计算与通信工程国际学术会议(HPCCE 2024) 2024 4th International Conference on High Performance Computing and Communication 第四届高性能计算与通信工程国际学术会议&#xff08;HPCCE 2024&#xf…

使用Chainlit接入通义千问快速实现一个自然语言转sql语言的智能体

文本到 SQL 让我们构建一个简单的应用程序&#xff0c;帮助用户使用自然语言创建 SQL 查询。 最终结果预览 ​ 先决条件 此示例有额外的依赖项。你可以使用以下命令安装它们&#xff1a; pip install chainlit openai​ 导入 应用程序 from openai import AsyncOpenAI…

扩展------零拷贝技术(Mmap,SendFile)

什么是零拷贝 零拷贝&#xff08;Zero-Copy&#xff09;是一种计算机操作技术&#xff0c;旨在减少数据在内存之间的拷贝次数&#xff0c;以提高数据传输的效率和性能。 传统的IO模式&#xff1a; 模拟网络传输数据运行过程&#xff1a; 用户态read()发起系统调用&#xff0c…

Flink中上游DataStream到下游DataStream的内置分区策略及自定义分区策略

目录 全局分区器GlobalPartitioner 广播分区器BroadcastPartitioner 哈希分区器BinaryHashPartitioner 轮询分区器RebalancePartitioner 重缩放分区器RescalePartitioner 随机分区器ShufflePartitioner 转发分区器ForwardPartitioner 键组分区器KeyGroupStreamPartitio…

力扣SQL50 第二高的薪水 ifnull() 分页

Problem: 176. 第二高的薪水 &#x1f468;‍&#x1f3eb; 参考题解 Code select ifNull((select distinct salaryfrom employeeorder by salary desclimit 1,1),null) as SecondHighestSalary

【Python数据结构与算法】分治----汉诺塔问题

题目&#xff1a;汉诺塔问题 描述 古代有一个梵塔&#xff0c;塔内有三个座A、B、C&#xff0c;A座上有n个盘子&#xff0c;盘子大小不等&#xff0c;大的在下&#xff0c;小的在上。三个座都可以用来放盘子。有一个和尚想把这n个盘子从A座移到C座&#xff0c;但每次只能允许移…

AWS SES 认证策略设置全攻略:轻松掌握简单步骤!

最近&#xff0c;我有机会设置 Amazon Simple Email Service&#xff08;以下简称&#xff1a;SES&#xff09;的认证策略&#xff0c;所以这次写下来作为备忘。 前言 Amazon Simple Email Service&#xff08;SES&#xff09;是一项通过 API 端点或 SMTP 接口进行邮件发送的服…

MySQL:VIEW视图

概述 MySQL 视图&#xff08;View&#xff09;是一种虚拟存在的表&#xff0c;同真实表一样&#xff0c;视图也由列和行构成&#xff0c;但视图并不实际存在于数据库中。行和列的数据来自于定义视图的查询中所使用的表&#xff0c;并且是在使用视图时动态生成的。 数据库中只…

从Notion Sites的推出,分析SaaS服务发展浪潮

引言 前段时间&#xff0c;Notion发布了新功能“Notion Sites”&#xff0c;允许用户直接在Notion中编辑页面并将其作为网站发布。其实在此之前&#xff0c;一些SaaS&#xff08;软件即服务&#xff09;软件也具有该功能&#xff0c;比如HelpLook AI知识库、Squarespace、Wix等…

buu做题(13)

[BSidesCF 2019]Kookie 给了一个账户: cookie / monster 根据提示, 我们需要以 admin 的身份登录 抓个包 , 可以发现一个奇怪的地方, Set-Cookie: usernamecookie; 以这样的方式确定登录的用户, 尝试伪造一下 直接 加上一个请求头: Cookie:usernameadmin 就可以得到flag 也…

卡码网--数组篇(二分法)

系列文章目录 文章目录 系列文章目录前言数组二分查找 前言 详情看&#xff1a;https://programmercarl.com/ 总结知识点用于复习 数组 概念: 数组是存放在连续内存空间上的相同类型数据的集合。 数组可以方便的通过下标索引的方式获取到下标对应的数据。 特点&#xff1a;…

图欧资源站与AI站23年5月~24年5月一年更新日志大汇总!

Hello&#xff0c;大家好&#xff0c;我是图欧君&#xff0c;很久没上CSDN啦&#xff0c;来跟大家一口气盘点一下我和我们团队从2023年5月到2024年5月以来都干了些什么大事吧~本文超长&#xff01;流量预警&#xff01;建议在WIFI环境下观看&#xff01; 别眨眼&#xff0c;三&…

python实现图像分割算法4

python实现流域变换算法 算法原理基本步骤数学模型Python实现详细解释优缺点应用领域流域变换(Watershed Transform)算法是一种用于图像分割的技术,特别适用于分割重叠和相邻的对象。它的基本思想是将图像视为拓扑表面,通过模拟水的流动来分割区域。流域变换广泛应用于医学…

Hadoop学习(三)

一、MapReduce框架原理 1.1InputFormat数据输入 MapTask并行度决定机制 1&#xff09;数据块&#xff08;HDFS存储数据单位&#xff09;&#xff0c;物理上把数据分成一块一块 2&#xff09;数据切片&#xff08;MapReduce程序计算输入数据的单位)&#xff1a;只是在逻辑上…

2.MySQL库的操作

创建数据库 创建数据库的代码&#xff1a; CREATE DATABASE [IF NOT EXISTS] db_name [create_specification [,create_specification] ...];​create_specification:[DEFAULT] CHARACTER SET charset_name[DEFAULT] COLLATE collation_name 说明&#xff1a; 大写的表示关键…

21天学通C++:理解函数对象、Lambda表达式

第二十一章&#xff1a;理解函数对象 函数对象&#xff08;也叫 functor&#xff09;。 函数对象与谓词的概念 从概念上说&#xff0c;函数对象是用作函数的对象&#xff1b; 但从实现上说&#xff0c;函数对象是实现了 operator() 的类的对象。 虽然函数和函数指针也可归…

数据结构之八大排序(下)

找往期文章包括但不限于本期文章中不懂的知识点&#xff1a; 个人主页&#xff1a;我要学编程(ಥ_ಥ)-CSDN博客 所属专栏&#xff1a;数据结构&#xff08;Java版&#xff09; 数据结构之八大排序&#xff08;上&#xff09;-CSDN博客 上面博客讲述了另外六中排序算法。 目…

仓颉 -- 标识符 , 变量以及数据类型详解

仓颉 – 标识符 , 变量以及数据类型 一. 标识符 1. 普通标识符 由数字 , 字母 , 下划线构成 – cangjie , cangjie_2024由英文字母开头&#xff0c;后接零至多个英文字母、数字或下划线。由一至多个下划线开头&#xff0c;后接一个英文字母&#xff0c;最后可接零至多个英文…

phpMyAdmin 漏洞复现教程

一.登陆 账号密码 是数据库的 二.日志文件拿到shell 在sql里执行命令 可以看到是关闭状态 我们再次执行命令 让它变成on 日志文件开启 再次执行上面的命令 可以看到已经开启了 然后我们更改日志保存路径 然后查看是否更改成功 显示 更改成功 然后我们插入一句话木马 访问一下…

完成订单业务

文章目录 概要整体架构流程技术细节小结 概要 完成订单是电子商务、外卖平台、在线零售等多个行业中的一项重要业务流程。这项功能允许商家或平台将订单状态更新为“已完成”&#xff0c;表明订单已经成功交付给客户。 需求分析以及接口设计 技术细节 1.Controller层: ApiOp…