equal()和hashcode()方法简析

简介: 由于equal()和hashcode()是object中的方法,所以每个类中都有这两个方法,但在实际应用中往往需要重写这两个方法。 重写equal()和hashcode()方法假设场景:java中的Set集合的特性之一是会去除相同的元素。

由于equal()和hashcode()是object中的方法,所以每个类中都有这两个方法,但在实际应用中往往需要重写这两个方法。

重写equal()和hashcode()方法
假设场景:java中的Set集合的特性之一是会去除相同的元素。假设在Set集合中存学生对象,同一个人只能在Set集合中存一次,判断一个学生是否是同一个人的依据为:姓名相同,年龄相同,即为同一人。
编写一个Student类:

public class Student {
    private String name;
    private Integer age;

    public Student(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

       //todo 添加get/set 方法

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

编写一个测试类:

public class SetTest {

    /**
     * 假设一场景:判断一个学生是否是同一个人的依据为:姓名相同,年龄相同,即为同一人
     * @param args
     */
    public static void main(String [] args){

        Set set = new HashSet();
        set.add(new Student("xiaoming",22));
        set.add(new Student("liangliang",24));
        set.add(new Student("xiaoming",22));
        set.add(new Student("daming",23));
        set.add(new Student("xiaoming",23));

        for (Iterator it =set.iterator();it.hasNext();){
            System.out.println(it.next());
        }
    }
}

测试结果:
image
显然,结果中出现两个xiaoming,年龄都为22,应该判断为一个人。出现这个结果是因为new出的每一个对象,哈希值是不同的, 想要实现预定的需求,必然要重写equal方法和hashcode方法。
在student类中重写这两个方法:

@Override
    public int hashCode() {
        return this.name.hashCode()+age * 31;
    }
    @Override
    public boolean equals(Object obj) {
        if(this == obj)
            return true;
        if(!(this instanceof Student)){
            throw  new ClassCastException("类型不一样");
        }
        Student stu = (Student) obj; 
        return this.age == stu.age && this.name == stu.name;
    }

重写equal方法和hashcode方法有多种,可以根据自己的实际需求来指定合适的重写方法。
测试结果:
image

实现所需要的结果。

思考:为什么要重写equal和hashcode方法,这两个方法的调用机制是什么?

java中引入hashcode的方法主要就是为了查找方便,如果是一个数组去实现,想要找到其中一个值,就需要一个一个去比较,在数据量很大的情况下,性能会特别差,用hashcode方法可以快速找到存储的位置。那是否只重写hashcode()方法就可以呢?答案是否定的。只覆写hashcode 的方法,还是得不到预期的结果,因为同名同年龄得到的哈希值是一样的,当hash值一样时,就会去比较equal方法,此时调用的是object中的equal()方法,比较的是地址,都是新new出对象,地址不一样,所以equal返回为false,判断出两个学生不是同一人,所以要同时覆写equal方法。

这两个调用机制是什么呢,是先调用equal()方法,还是先调用hashcode()方法,接下来做个小实验,在这两个方法中分别打印出调用的对象:


  @Override
    public int hashCode() {
        System.out.println(this.getName()+"调用hashcode方法:"+this.name.hashCode()+age * 31);
        return this.name.hashCode()+age * 31;
      //  return age ;
    }
    @Override
    public boolean equals(Object obj) {

        if(this == obj)
            return true;
        if(!(this instanceof Student)){
            throw  new ClassCastException("类型不一样");
        }
        Student stu = (Student) obj;
        System.out.println(this.getName()+"调用equal方法" +stu.getName());
        //此equal()方法为String中的方法
        return this.age == stu.age &&  this.name.equals( stu.name);
    }

测试结果:
image

所以,在比较是否为同一个人时,首先会调用它的hashcode()方法,只有当hashcode()值一样是才回去调用equal()方法。第二个xiaoming是先调用hashcode()方法,发现和第一个xiaoming的哈希值是星等的,才再去比较equal()方法。这种机制会减少很多比较,提升效率。

如果两个对象的hashcode值不同,则必是两个不同的对象;但,两个不同的对象所产生的hashcode值是可能一样的,称为哈希碰撞。

最后欣赏下IDEA自动生成的equal()和hashcode()方法:


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

    @Override
    public int hashCode() {

        return Objects.hash(name, age);
    }
目录
相关文章
Java 通过IP获取对应的国家省份城市经纬度(离线文件方案)
一. 除了调用接口查询城市, 还可以通过离线文件查询城市, 使用GeoLite2 City库 二. 离线库下载地址: https://dev.maxmind.com/geoip/geoip2/geolite2/ 点击如下位置下载压缩文件 文件解压后有一个文件名为GeoLite2-City.
|
存储 安全 Windows
Windows无法完成格式化怎么办?5种解决方法
在使用电脑时,我们有时会遇到“Windows无法完成格式化”的问题,这可能由磁盘写保护、权限限制、物理损坏或磁盘占用等原因引起。为解决这个问题,可以尝试关闭写保护开关、提升格式化权限、使用第三方工具、在CMD中用diskpart命令格式化或检查磁盘健康状况。如果磁盘有重要数据,可以先用数据恢复软件拯救数据。如果以上方法无效,可能需要专业售后检查修复或更换硬件。记得在操作前备份重要文件,以防数据丢失。
|
设计模式 JavaScript 前端开发
如何优雅的消除系统重复代码
在程序猿的日常工作中,不仅要跟随业务侧的发展不断开发新的需求,同时也需要维护老的已有平台。无论是开发新需求还是维护老系统,我们都会遇到同样一个问题,系统中总是充斥着很多重复的代码。
30037 11
如何优雅的消除系统重复代码
|
8天前
|
JavaScript API iOS开发
DeepSeek Harness下载、安装、配置一篇搞定(2026整理,送常用插件)
DeepSeek Harness(DSH)是DeepSeek于2026年开源的MIT协议AI Agent框架,支持插件化组装模型、工具、沙箱与UI,兼容主流大模型。本文提供免Node.js的桌面端安装包(Win/macOS),含详细图文教程及热门插件推荐。
3731 37
|
8天前
|
Linux 开发工具 iOS开发
Codex保姆级教程(下载+安装+登录+使用,含所有版本,2026最新)
Codex是OpenAI推出的开源AI编程智能体,本地运行,可理解整个代码库,支持自然语言指令改代码、执行命令、跑测试、修Bug,兼容Win/macOS/Linux。(239字)
3295 10
|
3天前
|
云安全 人工智能 安全
|
9天前
|
iOS开发 Docker MacOS
【2026实测】Docker Desktop下载、安装、汉化、配置教程(附官网安装包)
Docker Desktop 是 Docker 官方推出的桌面容器管理工具,集成引擎、CLI、图形界面与 Kubernetes,支持 Win/macOS/Linux。2026 最新版 4.88.1 强化 ARM 原生运行、镜像加速及资源可视化,附中文汉化与国内镜像配置指南。
1702 6
|
9天前
|
安全 算法 定位技术
《高性价比人生指南》完整原版:普通人用最少的资源,过好这一生的底层逻辑~How To Live Better
📖《高性价比人生指南》是一份基于实证、拒绝焦虑的生存手册,倡导以“人生时薪”为视角,重新计算时间、金钱与精力的成本与收益。它不承诺逆袭,只教人算清账:省下的钱若耗掉时间便亏;买体验比买物品更值;睡眠是最高杠杆的健康投资;关系贵在情绪价值而非表面热络;学习重在改变行为而非自我安慰。核心理念:用低成本、高回报的微小行动,换取长期的选择权——不是成为谁,而是掌控自己人生的主动权。
2035 4
|
云安全 安全 网络安全