深入完整的带你了解java对象的比较

news2024/9/25 7:17:59

 

目录

元素的比较

1.基本类型的比较

2.对象比较的问题

1.运行结果

2.疑问

3.原因

对象的比较

1.覆写基类的equals 

2.基于Comparble接口类的比较

3.基于比较器比较

4.三种方式对比 


元素的比较

1.基本类型的比较

在Java 中,基本类型的对象可以直接比较大小。

 public class TestCompare { 

     public static void main(String[] args) { ``
        int a =  10; 
        int b = 20; 
        System.out.println(a > b); 
        System.out.println(a < b); 
        System.out.println(a == b);
        
        char c1 = 'A'; 
        char c2 = 'B'; 
        System.out.println(c1 > c2); 
        System.out.println(c1 < c2); 
        System.out.println(c1 == c2); 
 
        boolean b1 = true; 
        boolean b2 = false;
        System.out.println(b1 == b2);                             
        System.out.println(b1 != b2); 
    } 
} 

2.对象比较的问题

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 main(String[] args) { 
           Card c1 = new Card(1, "♠"); 
           Card c2 = new Card(2, "♠"); 
           Card c3 = c1; 
           //System.out.println(c1 > c2);   // 编译报错 
           System.out.println(c1 == c2);  // 编译成功 ----> 打印false ,因为c1和c2指向的是不同对象 
           //System.out.println(c1 < c2);   // 编译报错 
           System.out.println(c1 == c3);  // 编译成功 ----> 打印true ,因为c1和c3指向的是同一个对象 
       } 
 } 

1.运行结果

c1、c2和c3分别是Card类型的引用变量,上述代码在比较编译时:

c1 > c2 编译失败

c1== c2 编译成功

c1 < c2 编译失败

2.疑问

从编译结果可以看出,Java 中引用类型的变量不能直接按照 > 或者 < 方式进行比较。 那为什么==可以比较?

3.原因

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

下面代码Object中equal的实现 ,可以看到 :直接比较的是两个引用变量的地址  

// Object中equal的实现 ,可以看到 :直接比较的是两个引用变量的地址 

public boolean equals(Object obj) { 

    return (this == obj); 
}

对象的比较

有些情况下,需要比较的是对象中的内容,比如:向优先级队列中插入某个对象时,需要对按照对象中内容来调整课

堆,那该如何处理呢?

1.覆写基类的equals 

public class Card { 

    public int rank;    // 数值                          

    public String suit; // 花色 

    public Card(int rank, String suit) {  

       this.rank = rank; 

       this.suit = suit; 

   }                         

   @Override 

    public boolean equals(Object o) { 

       //  自己和 自己比较 

       if (this == o) { 

            return true; 

       } 
       
       // o如果是null对象 ,或者o不是Card的子类 

       if (o == null  || !(o instanceof Card)) { 

            return false; 

       } 

       // 注意基本类型可以直接比较 ,但引用类型最好调用其equal方法 

       Card c = (Card)o; 

        return rank == c.rank 

           && suit.equals(c.suit); 

   } 
}

注意: 一般覆写 equals 的套路就是上面演示的

  1. 如果指向同一个对象,返回 true 
  2. 如果传入的为 null ,返回 false 
  3. 如果传入的对象类型不是 Card ,返回 false 
  4. 按照类的实现目标完成比较,例如这里只要花色和数值一样,就认为是相同的牌
  5. 注意下调用其他引用类型的比较也需要 equals ,例如这里的 suit 的比较 

覆写基类equal的方式虽然可以比较,但缺陷是:equal只能按照相等进行比较,不能按照大于、小于的方式进行比较。

2.基于Comparble接口类的比较

Comparble是JDK 提供的泛型的比较接口类,源码实现具体如下:

public interface Comparable<E> { 
   // 返回值: 
   // < 0:  表示 this 指向的对象小于 o 指向的对象 
   // == 0: 表示 this 指向的对象等于 o 指向的对象    // > 0:  表示 this 指向的对象大于 o 指向的对象       
   int compareTo(E o); 
} 

   // 返回值: 
   // < 0:  表示 this 指向的对象小于 o 指向的对象 
   // == 0: 表示 this 指向的对象等于 o 指向的对象    // > 0:  表示 this 指向的对象大于 o 指向的对象   

对用用户自定义类型,如果要想按照大小与方式进行比较时:在定义类时,实现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 rank - o.rank; 

   } 
    
    public static void main(String[] args){ 

       Card p = new Card(1, "♠"); 

       Card q = new Card(2, "♠"); 

       Card o = new Card(1, "♠"); 

       System.out.println(p.compareTo(o));     // == 0 ,表示牌相等 

       System.out.println(p.compareTo(q));     // < 0 ,表示  p 比较小 

       System.out.println(q.compareTo(p));     // > 0 ,表示 q 比较大 

   } 
}

Compareble是java.lang 中的接口类,可以直接使用。

3.基于比较器比较

按照比较器方式进行比较,具体步骤如下:

  •    用户自定义比较器类,实现Comparator接口 


       public interface Comparator<T> { 

          // 返回值: 

          // < 0: 表示 o1 指向的对象小于 o2 指向的对象 

          // == 0: 表示 o1 指向的对象等于 o2 指向的对象 

          // > 0: 表示 o1 指向的对象等于 o2 指向的对象 

          int compare(T o1, T o2); 

      }                                                                            

  注意:区分Comparable和Comparator。 

  •    覆写Comparator中的compare方法                                             
import j ava.util.Comparator;                                             

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

class CardComparator implements Comparator<Card> { 
          // 根据数值比较 ,不管花色 
          // 这里我们认为  null 是最小的 
          @Override 
           public int compare(Card o1, Card o2) { 
              if (o1 == o2) { 
                   return 0; 
              }
              if (o1 == null) { 
                   return -1; 
              } 
              if (o2 == null) { 
                  return  1; 
              } 
              return o1.rank - o2.rank; 
         } 

          public static void main(String[] args){ 
             Card p = new Card(1, "♠"); 
             Card q = new Card(2, "♠"); 
             Card o = new Card(1, "♠"); 
             // 定义比较器对象 
             CardComparator cmptor = new CardComparator(); 
             // 使用比较器对象进行比较 
             System.out.println(cmptor.compare(p, o));       // == 0 ,表示牌相等 
             System.out.println(cmptor.compare(p, q));       // < 0 ,表示  p 比较小 
             System.out.println(cmptor.compare(q,  p));       // > 0 ,表示 q 比较大 

         } 
} 

注意:Comparator是java.util 包中的泛型接口类,使用时必须导入对应的包。

4.三种方式对比 

覆写的方法                说明

Object.equals                因为所有类都是继承自 Object 的,所以直接覆写即可,不过只能比较相等与就否 

Comparable.compareTo                需要手动实现接口,侵入性比较强,但一旦实现,每次用该类都有顺序,属于内部顺序

Comparator.compare                需要实现一个比较器对象,对待比较类的侵入性弱,但对算法代码实现侵入性强

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

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

相关文章

52所韩国大学联合退出QS世界大学排名

因今年QS的全新评估指标&#xff0c;令韩国大学在世界大学的排名中大幅下降&#xff0c;因此韩国52所大学联合发表声明&#xff0c;将不再参加QS世界大学排名。下面知识人网小编做详细介绍。 今年6月28日&#xff0c;QS教育集团正式发布了2024年世界大学排名&#xff0c;见“排…

609. 在系统中查找重复文件

609. 在系统中查找重复文件 原题链接&#xff1a;完成情况&#xff1a;解题思路&#xff1a;参考代码&#xff1a; 原题链接&#xff1a; 609. 在系统中查找重复文件 https://leetcode.cn/problems/find-duplicate-file-in-system/description/ 完成情况&#xff1a; 解题思…

网络编程(三次握手、四次挥手)

一、Wireshark 窗口介绍 二、 wireshark与对应的OSI七层模型 服务器和客户端的代码不能都运行在ubuntu&#xff0c;因为wireshark抓的是流经真实网卡的数据包。 若将服务器客户端都运行在ubuntu&#xff0c;数据直接经过虚拟网卡通信&#xff0c;而不会经过真实网卡。 三、以太…

QT样式表(一)

目录 QSS样式表设置 1、概念 1、通过UI设计器的可视操作修改 2、通过代码修改 3、从样式文件加载 2、样式表语法 选择器的类型 3、设置背景图片 1、添加资源文件 2、使用label控件 显示头像&#xff0c;在样式表文件中进行设置 3、在项目中添加图片资源 QSS样式表设…

动态规划入门之二维数组的动态规划(过河卒)

P1002 [NOIP2002 普及组] 过河卒 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 过河卒&#xff0c;首先科普一下象棋里面的马的跳跃一步的规则吧&#xff08;这题真够坑人的&#xff0c;连个规则都不给出&#xff0c;害得我第一次交就全wa&#xff09;。一张图解释 大家看所…

Nvidia Jetson 编解码开发(4)H265解码图像异常问题调试

1. 前言 基于此贴继续验证H265图像 Nvidia Jetson 编解码开发(3)解决H265解码报错“PPS id out of range”_free-xx的博客-CSDN博客 ffmpeg解码后图像颜色异常 2. 梳理YUV格式顺序 相机输出图像格式: YUV422 8bit, UYVY 由于编码模块输入必须是 YUV420, 不能是YUV…

SpringCloud Ribbon中的7种负载均衡策略

SpringCloud Ribbon中的7种负载均衡策略 Ribbon 介绍负载均衡设置7种负载均衡策略1.轮询策略2.权重策略3.随机策略4.最小连接数策略5.重试策略6.可用性敏感策略7.区域敏感策略 总结 负载均衡通器常有两种实现手段&#xff0c;一种是服务端负载均衡器&#xff0c;另一种是客户端…

内网渗透神器CobaltStrike之权限提升(七)

Uac绕过 常见uac攻击模块 UAC-DLL UAC-DLL攻击模块允许攻击者从低权限的本地管理员账户获得更高的权限。这种攻击利用UAC的漏洞&#xff0c;将ArtifactKit生成的恶意DLL复制到需要特权的位置。 适用于Windows7和Windows8及更高版本的未修补版本 Uac-token-duplication 此攻…

软件测试开发实战|接口自动化测试框架开发(pytest+allure+aiohttp+用例自动生成)

近期准备优先做接口测试的覆盖&#xff0c;为此需要开发一个测试框架&#xff0c;经过思考&#xff0c;这次依然想做点儿不一样的东西。 接口测试是比较讲究效率的&#xff0c;测试人员会希望很快能得到结果反馈&#xff0c;然而接口的数量一般都很多&#xff0c;而且会越来越…

鼎友餐饮信息总监杨山海:餐饮新增长依托数智应用,用数字化打造单店盈利模型

杨山海 鼎友餐饮信息总监 近20年餐饮行业信息化、数字化决策经验&#xff0c;曾担任新辣道、雕刻时光、青年餐厅、快乐蜂、鲜果时间信数化负责人&#xff0c;主抓数字化转型、系统选型、多接口系统管理等&#xff0c;拥有丰富的餐饮行业数字化转型经验。 2000年&#xff0c;杨…

vue快捷生成初始代码模板

1.在 vscode 中找到如图设置->代码片段->vue.json 2.配置默认值 {"vue3": {"prefix": "vue3","body": ["<template>"," <div></div>","</template>","",&qu…

【HCIP】09.路由引入

路由引入&#xff1a;路由优先级 路由引入&#xff1a;路由回灌 场景描述 R1访问目标地址5.5.5.5&#xff0c;如果数据发给R3就会形成路由回灌R1访问5.5.5.5时&#xff0c;查询路由表&#xff0c;发现5.5.5.5是R3将ISIS引入产生的路由&#xff0c;则将下一跳指向R3R3收到数据包…

arm:day7

1.软中断处理 .text 文本段 .global _start 声明一个_start全局函数的入口 _start: _start标签&#xff0c;就是c语言的函数 1.构建异常表b resetb undefb softwareb prefetchb datab irqb fiqreset: 2.系统上电&#xff0c;程序运行在svc模式 初始化svc模式的栈指针ldr sp,0x4…

财报解读:“三驾马车”驱动,劲仔食品能否越跑越快?

国内休闲零食市场上半年表现喜人。 8月以来&#xff0c;多家休闲零食上市公司发布半年报告或预告&#xff0c;纷纷迎来利润增长。盐津铺子预计2023年上半年实现扣除非经常性损益后的净利润2.26亿元至2.36亿元&#xff0c;同比增长98.89%至107.69%&#xff1b;甘源食品预计2023…

【Java转Go】快速上手学习笔记(四)之基础篇三

目录 泛型内置泛型的使用切片泛型和泛型函数map泛型泛型约束泛型完整代码 接口反射协程特点WaitGroupgoroutine的调度模型&#xff1a;MPG模型 channel介绍语法&#xff1a;举例&#xff1a;channel遍历基本使用和协程一起使用案例一案例二 select...casemain.go 完整代码 文件…

备份服务器搭建

备份服务器搭建 1、背景2、作用3、选型4、环境5、部署5.1、服务端部署5.1.1、安装5.1.2、配置 5.2、客户端部署5.3、备份策略5.3.1、定时备份策略5.3.2、文件变动备份 6、参考 1、背景 随着项目的推进&#xff0c;备份服务器被提上了工作日程&#xff0c;等保、密评和接入测评…

三层交换机实验

要求&#xff1a; 目录 1、IP规划 2、交换机的配置 2.1 Eth-Trunk通道&#xff08;将多个接口逻辑的整合成一个接口&#xff0c;实现带宽叠加的作用&#xff09; 2.2 创建VLAN&#xff08;所有交换机只创建VLAN2&#xff0c;默认有VLAN1&#xff09; 2.3 创建trunk干道…

PHP“牵手”拼多多商品详情数据获取方法,拼多多API接口批量获取拼多多商品详情数据说明

拼多多商品详情接口 API 是开放平台提供的一种 API 接口&#xff0c;它可以帮助开发者获取拼多多商品的详细信息&#xff0c;包括商品的标题、描述、图片等信息。在拼多多电商平台的开发中&#xff0c;拼多多详情接口 API 是非常常用的 API&#xff0c;因此本文将详细介绍拼多多…

6.RocketMQ之文件查询索引文件IndexFile

根据消息ID来查找消息&#xff0c;consumequeue 中没有存储消息ID,如果不采取其他措施&#xff0c;又得遍历 commitlog文件了&#xff0c;indexFile就是为了解决这个问题的文件。 如图所示&#xff1a; 一个indexFile对应一个40个字节的IndexHead。(40,2000 0000]区间代表存放…

【深入解析:数据结构栈的魅力与应用】

本章重点 栈的概念及结构 栈的实现方式 数组实现栈接口 栈面试题目 概念选择题 一、栈的概念及结构 栈&#xff1a;一种特殊的线性表&#xff0c;其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端 称为栈顶&#xff0c;另一端称为栈底。栈中的数…