Java中对象的比较(equals、Comparable、Comparator)

news2024/11/25 13:52:56

文章目录

  • 一、PriorityQueue中插入对象
  • 二、元素的比较
    • 2.1、基本类型的比较
    • 2.2、对象比较的问题
  • 三、对象的比较
    • 3.1、覆写基类的equals
    • 3.2、基于Comparable接口类的比较
    • 3.3、基于比较器比较
    • 3.4、三种方式对比

一、PriorityQueue中插入对象

前篇我们讲解了优先级队列,大家应该还记得,其内部是按照小根堆的方式实现的,插入元素的前提是不为null或者元素必须能够比较,为了方便我们当时插入的为Integer类型的元素,那如果我们插入自定义类型对象呢?

class Card {
    public int rank; // 数值
    public String suit; // 花色
    public Card(int rank, String suit) {
        this.rank = rank;
        this.suit = suit;
    }
}
public class TestPriorityQueue {
    public static void TestPriorityQueue()
    {
        PriorityQueue<Card> p = new PriorityQueue<>();
        p.offer(new Card(1, "♠"));
        p.offer(new Card(2, "♠"));
    }
    public static void main(String[] args) {
        TestPriorityQueue();
    }
}

如上代码,优先级队列的底层使用堆,向堆中插入元素时,为了满足堆的性质,必须要进行元素的比较,而此时Card为自定义数据类型,是没有办法直接进行比较的,因此抛出异常。 

 那么怎么做才能比较自定义数据类型呢?我们往下看:

二、元素的比较

2.1、基本类型的比较

在Java中,基本类型的元素是可以直接比较大小的,如下(注释为输出结果): 

2.2、对象比较的问题

class Card {
    public int rank; // 数值
    public String suit; // 花色
    public Card(int rank, String suit) {
        this.rank = rank;
        this.suit = suit;
    }
}

public class text {
    public static void main(String[] args) {
        Card c1 = new Card(1, "♠");
        Card c2 = new Card(1, "♠");
        Card c3 = c1;
    }
}

1、c1==c2

        c1,c2分别new了一个Card类型的对象,分别指向不同的对象,其地址也不同,所以会打印false

2、c1.equals(c2):

        我们的Card类默认继承Object类的,Object类中实现了equals方法,所以我们能够直接调用,但为什么是false呢?我们点进源码看到,其返回的就是c1==c2

3、c1==c3:

        c1c3指向同一个对象,过其返回true 

那么当我们用><符号进行比较时,会发生什么?

我们可看出Java中引用类型的变量不能直接按照 > 或者 < 方式进行比较,为什么可以使用==进行比较呢?

因为:

        对于用户实现自定义类型,都默认继承自Object类,而Object类中提供了equal方法,而==默认情况下调 用的就是equal方法,但是该方法的比较规则是:没有比较引用变量引用对象的内容,而是直接比较引用变量的地址

三、对象的比较

3.1、覆写基类的equals

那么,我们在Card中重写Object类中的equals方法

public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Card card = (Card) o;
        return rank == card.rank && Objects.equals(suit, card.suit);
    }

 我们发现c1.equals(c2)就返回true

重写的equals

1. 如果指向同一个对象,返回 true

2. 如果传入的为 null,返回 false

3. 如果传入的对象类型不是 Card,返回 false

4. 按照类的实现目标完成比较,例如这里只要花色和数值一样,就认为是相同的牌

5. 注意下调用其他引用类型的比较也需要 equals,例如这里的 suit 的比较 

缺陷:equal 只能按照相等进行比较,不能按照大于、小于的方式进行比较 

3.2、基于Comparable接口类的比较

对于用户自定义的数据类型,如果想按照大小与方式进行比较时:在定义类时,实现Comparble接口即可,然后在类中重写compareTo方法。

public class Card implements Comparable<Card> {
    public int rank; // 数值
    public String suit; // 花色
    public Card(int rank, String suit) {
        this.rank = rank;
        this.suit = suit;
    }
    // 根据数值比较,不管花色
// 这里我们认为 null 是最小的
    @Override
    public int compareTo(Card o) {
        if (o == null) {
            return 1;
        }
        return this.rank - o.rank;
    }
}

我们就按照期待的结果(按照数值比较)成功比较出c1和c2的数值大小关系 :

注意:Compareblejava.lang中的接口类,可以直接使用。 

3.3、基于比较器比较

上述我们可以比较自定义类型的数值,那么花色的比较要实现Comparator接口,重写compare方法:

class suitComparator implements Comparator<Card> {
    @Override
    public int compare(Card o1, Card o2) {
        return o1.suit.compareTo(o2.suit);
    }
}
public static void main(String[] args) {
        Card c1=new Card(12,"♥");
        Card c2=new Card(13,"♠");
        suitComparator com=new suitComparator();
        if(com.compare(c1,c2)>0){
            System.out.println("c1 > c2");
        }else{
            System.out.println("c1 < c2");
        }

        if(com.compare(c1,c3)>0){
            System.out.println("c1 > c3");
        }else{
            System.out.println("c1 < c3");
        }

        if(com.compare(c2,c3)>0){
            System.out.println("c2 > c3");
        }else{
            System.out.println("c2 < c3");
        }
    }
//结果:
//    c1 > c2
//    c1 > c3
//    c2 < c3

我们就成功比较出Card类对象的花色大小。 

3.4、三种方式对比

        Comparable是Java中一个接口,它用于实现对象的比较。如果一个类实现了Comparable接口,就意味着该类的对象是可以排序的。Comparable接口中只有一个方法compareTo(Object o),该方法用于比较对象的大小关系。

        equals是Java中一个方法,用于比较两个对象是否相等。equals方法实际上是用来比较两个对象的内容是否相等,而不是比较对象的引用是否相等。equals方法通常会被重写,以实现自定义的相等逻辑。

        Comparator是Java中一个接口,它可以用于实现两个对象的比较。Comparator接口中有一个方法compare(Object o1, Object o2),该方法用于比较o1和o2的大小关系。Comparator接口可以用于对任意的对象进行排序,而不需要修改对象的定义,因此它具有更大的灵活性。

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

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

相关文章

mpi 示例小程序集锦

1&#xff0c;小ring 程序 数据从rank 0开始向外传递&#xff0c;rank1收到后再传递给 rank2&#xff0c;以此类推 除了rank0&#xff0c;程序一开始时&#xff0c;每个rank先进入接收等待状态&#xff0c;像是多米诺骨牌&#xff0c;都立起来。 rank 0开始倒下&#xff0c;依…

设备管理系统:强化特种设备安全监管的智能引擎

设备管理系统在特种设备安全监管中发挥着至关重要的作用&#xff0c;主要体现在以下几个方面&#xff1a; 一、实时监控与预警 运行状态监控&#xff1a;设备管理系统能够实时监控特种设备的运行状态&#xff0c;包括开机时间、运行时间、停机时间等关键参数。这有助于及时发现…

初级网络工程师之从入门到入狱(六)

本文是我在学习过程中记录学习的点点滴滴&#xff0c;目的是为了学完之后巩固一下顺便也和大家分享一下&#xff0c;日后忘记了也可以方便快速的复习。 网络工程师从入门到入狱 前言一、vlan与vlanif二、路由器之三层通信方式2.1、路由器物理接口2.2、子接口2.3、vlanif 三、数…

Tars简介

定义&#xff1a;Tars协议的高性能rpc开发框架 功能&#xff1a;可扩展协议编解码、高性能rpc通信框架、名字路由和发现、发布监控、日志统计、配置管理 整体架构 交互流程 1.服务发布 2.管理命令 3.心跳上报 4.信息上报 server服务运行后&#xff0c;会定期上报统计信息到s…

高中毕业|转行AI产品经理经验都在这了

从高中毕业以后第一份客服工作➡️设计师➡️产品➡️AI产品&#xff0c;从月薪4k到年薪22w&#xff0c;我觉得在转行这方面我太有发言权了&#xff0c;所以今天为大家整理我的转行经验&#xff0c;希望能帮助到大家&#xff01; 找工作&#xff0c;大家胆子一定要大&#xff0…

10月10日微语报,星期四,农历九月初八

10月10日微语报&#xff0c;星期四&#xff0c;农历九月初八&#xff0c;工作愉快&#xff0c;生活喜乐&#xff01; 一份微语报&#xff0c;众览天下事&#xff01; 1、从严处置&#xff01;网信部门曝光“毒视频”“开盒挂人”等涉未成年人乱象。 2、A股新纪录诞生&#x…

Windows 下纯手工打造 QT 开发环境

用过 QtCreator 和 VS QT 插件&#xff0c;都觉得不是很理想。所以有了这个想法。 手工打造的 QT 的开发环境&#xff0c;是不需要安装上面两个程序的。 1、下载 vcpkg&#xff0c;编译 QT6 下载地址&#xff1a;https://github.com/microsoft/vcpkg.git 进入到 …

mac本地VSCode配置LeetCode

1、安装node.js及环境配置 https://www.jb51.net/article/283302.htm mac配置后如何找到Node地址 打开终端&#xff0c;输入which node 2、安装leetcode插件 https://zhuanlan.zhihu.com/p/488602193 3、mac配置力扣插件 https://juejin.cn/post/7050349897756704805 4、登…

前瞻性的索引设计

目录 介绍两个快速、易用的技术&#xff1a;基本问题法&#xff08;BQ&#xff09;和快速上限估算法&#xff08;QUBE&#xff09; 发现不合适的索引 基本问题法 对每个SELECT语句&#xff0c;以下问题的答案都必须按下述步骤来考虑 如何确定一个方案能否让SELECT在最差输…

PostgreSQL 专栏已全部完成

PostgreSQL 专栏历时近半年&#xff0c;终于完成了。 目前已整理成册&#xff0c;可以看下截图&#xff1a; 目录预览 目录 01 预览&#xff1a; 目录 02 预览&#xff1a; 目录 03 预览&#xff1a; 目录 04 预览&#xff1a; 目录 05 预览&#xff1a; 目录 06 预览&…

罗格科技:全球税务服务领域初露锋芒 罗格罗拉国际税大模型发布

近年来&#xff0c;随着全球数字经济和跨境电商的迅猛发展&#xff0c;税务问题已成为中国企业出海过程中不可忽视的重要环节。为了帮助企业应对国际税务挑战&#xff0c;国内领先的数据科学与税务科技服务供应商罗格科技&#xff0c;携其最新成果——罗格罗拉国际税大模型&…

[内容转载] 微信全平台开源终端数据库WCDB迎来重大升级!

第一次看到这么详实的文章&#xff0c;转给大家看看&#xff0c;很多提出问题和如何解决问题的方法因为太细了&#xff0c;就没有完全转载&#xff0c;感兴趣的可以去看原文。 一、简介 WCDB 是微信团队开源的一款基于 SQLite 的终端数据库。自 2017 年 6 月开源以来&#xff…

【C++】STL——stack和queue

目录 前言容器配接器&#xff08;适配器&#xff09;stack的使用stack的模拟实现queue的使用queue的模拟实现双端队列&#xff08;deque&#xff09; 前言 前面我们已经学习了STL容器中的string、vector还有list。 【C】string的模拟实现 【C】STL——vector的模拟实现 【C】S…

gradle降级

文章目录 引子编译错误参考 引子 项目引入了一个高版本项目改造&#xff0c;编译运行失败&#xff0c;提示如下错误&#xff0c;解决方案要么升级gradle版本&#xff0c;升级适配改各种方法配置&#xff0c;现有的项目存在适配问题&#xff1b;要么就是版本降级。 本文以介绍…

docker环境redis启动失败

现象&#xff1a; 查看日志错误为 Bad file format reading the append only file: make a backup of your AOF file, then use ./redis-check-aof --fix <filename> 经查询为aof文件损坏导致&#xff0c;修复aof即可 解决方法&#xff1a; 1.查看执行的docker命令&…

c到c++衔接速成

温馨提示&#xff1a;本篇文章乃博主多次学习后的总结&#xff0c;其中一些专业名词的概念不会做介绍&#xff0c;本篇文章只解决实操问题 c到c中&#xff0c;语法上得到了许多升级&#xff0c;那么哪些地方升级了&#xff0c;我们来快速复习一下 目录 头文件的升级 命名空间…

国产长芯微LDC5791是一款单通道、20位、无缓冲电压输出DAC完全P2P替代AD5791

描述 LDC5791是一款单通道、20位、无缓冲电压输出DAC&#xff0c;采用最高33 V的双极性电源供电。正基准电压输入范围为5 V至VDD – 2.5V&#xff0c;负基准电压输入范围为VSS 2.5 V至0 V。相对精度最大值为1 LSB&#xff0c;保证工作单调性&#xff0c;差分非线性(DNL)最大值…

基于echarts的旅游信息(游客行为分析)大数据可视化平台(echarts+Django+MySQL+Scrapy框架爬虫;程序+论文+开题报告)

摘要 本论文旨在研究Python技术和ECharts可视化技术在游客行为分析系统中的应用&#xff0c;通过对旅游数据的深入分析&#xff0c;希望能够揭示出南京旅游市场的现状和趋势&#xff0c;从而为游客提供更优质的旅游体验&#xff0c;也可以为政府和旅游企业制定更加科学和有效的…

Spring事务的1道面试题

每次聊起Spring事务&#xff0c;好像很熟悉&#xff0c;又好像很陌生。本篇通过一道面试题和一些实践&#xff0c;来拆解几个Spring事务的常见坑点。 原理 Spring事务的原理是&#xff1a;通过AOP切面的方式实现的&#xff0c;也就是通过代理模式去实现事务增强。 具体过程是…

2024年诺贝尔物理学奖

2024年&#xff0c;诺贝尔物理学奖没有颁给物理学家&#xff0c;而是授予了两位计算机科学家&#xff0c;表彰他们在神经网络领域的开创性工作&#xff0c;这项研究成为了我们今天所称的人工智能的基础。这标志着物理学与计算机科学之间的深度融合。 获奖者约翰霍普菲尔德和杰弗…