博客
关于我
Java中为什么要重写 hashcode 和 equals 方法
阅读量:155 次
发布时间:2019-02-28

本文共 2222 字,大约阅读时间需要 7 分钟。

为什么要重写 hashcode 和 equals 方法

在面试Java初级开发时,提到自定义类在HashMap中存储时遇到的问题,往往会引发关于equalshashCode方法的讨论。很多候选人表示自己从未重写过这两个方法,这不仅会导致实际开发中遇到问题,还可能在面试中暴露对Java内存管理和集合机制的理解不足。本文将从HashMap的存储规则入手,解释为什么要重写hashCodeequals方法,以及它们的重要性。


1. 理解Hash算法与HashMap的高效性

Hash表(即哈希表)是一种高效的数据结构,能够在平均O(1)时间内完成查找、插入和删除操作。与传统的线性表(如ArrayList)相比,Hash表的平均查找时间从O(n/2)显著降低到O(1)。

Hash表的核心原理是通过将键(Key)和值(Value)映射到一个特定位置(Index),称为Hash值。Java中的HashMap采用了链地址法来解决Hash冲突。


2. 为什么要重写equals和hashCode方法

当我们将自定义对象存入HashMap时,如果不重写hashCodeequals方法,可能会遇到以下问题:

示例分析:WithoutHashCode.java

import java.util.HashMap;class Key {    private Integer id;    public Key(Integer id) {        this.id = id;    }    // hashCode和equals方法被注释掉}public class WithoutHashCode {    public static void main(String[] args) {        Key k1 = new Key(1);        Key k2 = new Key(1);        HashMap
hm = new HashMap<>(); hm.put(k1, "Key with id is 1"); System.out.println(hm.get(k2)); }}
  • 问题1:无法通过相同值的对象正确取值

    • hashCode方法未重写,k1k2hashCode值分别为它们的内存地址。由于k1k2是不同的对象,hashCode值不同,导致无法通过k2取到对应的值。
  • 问题2:无法正确判断对象相等

    • equals方法未重写,k1k2会被视为两个不同的对象,无法找到正确的链表节点。

重写方法后的效果

class Key {    private Integer id;    public Key(Integer id) {        this.id = id;    }    public boolean equals(Object o) {        if (o == null || getClass() != o.getClass()) {            return false;        }        Key key = (Key) o;        return Objects.equals(id, key.id);    }    public int hashCode() {        return id != null ? id.hashCode() : 0;    }}public class WithoutHashCode {    public static void main(String[] args) {        Key k1 = new Key(1);        Key k2 = new Key(1);        HashMap
hm = new HashMap<>(); hm.put(k1, "Key with id is 1"); System.out.println(hm.get(k2)); // 输出:"Key with id is 1" }}
  • 效果1:相同值的对象能正确取值

    • k1k2hashCode值相同,存储在同一个链表节点下。
  • 效果2:能正确判断对象相等

    • equals方法判断对象的id是否相等,确保k2能找到k1的链表节点。

3. 对面试问题的说明

在面试中,提到hashCodeequals方法时,可以深入探讨以下问题:

  • 你有没有重写过hashCode方法?

    • 回答:有,重写了hashCode方法,确保每个对象的hashCode与其属性值相关联。
  • 你在使用HashMap时有没有重写hashCodeequals方法?

    • 回答:是的,重写了这两个方法,以确保自定义对象能正确存储和查找。
  • 你是怎么写的?

    • 回答:我重写了hashCode方法,使用对象的属性值计算哈希码。同时,重写了equals方法,判断对象的属性是否相等。

结论

重写hashCodeequals方法的主要作用是确保自定义对象能像预期一样存储和查找。这种做法不仅避免了哈希冲突,还能保证HashMap正确地找到目标对象。对于开发人员来说,这是基础的OOP知识,熟练掌握它对项目开发和面试中都至关重要。

转载地址:http://fcpc.baihongyu.com/

你可能感兴趣的文章
nacos源码 nacos注册中心1.4.x 源码 nacos源码如何下载 nacos 客户端源码下载地址 nacos discovery下载地址(一)
查看>>
nacos源码 nacos注册中心1.4.x 源码 spring cloud alibaba 的discovery做了什么 nacos客户端是如何启动的(二)
查看>>
nacos源码 nacos注册中心1.4.x 源码 如何注册服务 发送请求,nacos clinet客户端心跳 nacos 注册中心客户端如何发送的心跳 (三)
查看>>
Nacos源码分析:心跳机制、健康检查、服务发现、AP集群
查看>>
nacos看这一篇文章就够了
查看>>
Nacos简介、下载与配置持久化到Mysql
查看>>
Nacos简介和控制台服务安装
查看>>
Nacos管理界面详细介绍
查看>>
Nacos编译报错NacosException: endpoint is blank
查看>>
nacos自动刷新配置
查看>>
nacos运行报错问题之一
查看>>
Nacos部署中的一些常见问题汇总
查看>>
NACOS部署,微服务框架之NACOS-单机、集群方式部署
查看>>
Nacos配置Mysql数据库
查看>>
Nacos配置中心中配置文件的创建、微服务读取nacos配置中心
查看>>
Nacos配置中心集群原理及源码分析
查看>>
nacos配置在代码中如何引用
查看>>
nacos配置新增不成功
查看>>
nacos配置自动刷新源码解析
查看>>
nacos集成分布式事务插件Seata的序列化问题,实际上是Seata本身存在bug!!
查看>>