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

2023-11-02

 

目录

元素的比较

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                需要实现一个比较器对象,对待比较类的侵入性弱,但对算法代码实现侵入性强

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

深入完整的带你了解java对象的比较 的相关文章

随机推荐

  • nginx部署vue项目并访问后端接口遇到 503 服务器不可用

    nginx部署vue项目并访问后端接口遇到Uncaught in promise Error Request failed with status code 503 今天在一台阿里云上部署了springboot后端 并测试通过 但是在部署v
  • pytorch版本官网命令

    COMMANDS FOR VERSIONS gt 1 0 0 v1 8 0 Conda OSX conda conda install pytorch 1 8 0 torchvision 0 9 0 torchaudio 0 8 0 c p
  • 多维时序

    多维时序 MATLAB实现GWO GRU灰狼算法优化门控循环单元的多变量时间序列预测 目录 多维时序 MATLAB实现GWO GRU灰狼算法优化门控循环单元的多变量时间序列预测 预测效果 基本介绍 程序设计 参考资料 预测效果 基本介绍 M
  • homestead实现外部局域网络其他主机的访问

    homestead 2 0 MAC环境 修改Homestead目录下的Vagrantfile文件 加上这么一行 config vm network public network ip 192 168 1 XXX IP地址为该局域网内其他未被
  • 手把手教你写购物车(完整篇1)

    购物车的设计与思路 1 在做任何业务的时候 首先要做的是把思路的流程捋清楚 再进行代码的编写 以及实现 2 对业务涉及到的技术 如果没接触过的 首先要学习至会用为止 3 如果思路不是很清楚的 可以查找类似的案列情况 学习思路流程 4 具体的
  • 攻克3D神器Blender的第五天-【多边形建形、旋转】

    目录 前言回顾 功能预览 多边形建形 旋转 前言回顾 不熟悉快捷键属性的可以点击传送门预览 传送门 官网地址 传送门 攻克3D神器Blender的第一天 快捷键 传送门 攻克3D神器Blender的第二天 挤出 传送门 攻克3D神器Blen
  • 笔记:《深入浅出统计学》第五章:概率分布(均值、方差、线性变换)

    随机变量的概率分布是描述随机变量取所有不同值的概率 对于随机变量x 概率函数给出随机变量取每一种值的概率 记f x 离散型概率函数的基本条件 1 对于任意随机变量的取值 函数值都是大于等于0 2 随机变量的所有取值对应的概率之和为1 常见的
  • 【C语言】符号常量(#define)

    举例 define XY RX 100 用法 define 标识符 常量 其中 标识符一般全大写 单词之间用 下划线分割
  • gin库的的理解以及简单使用

    gin库的作用 在实验当中 可能存在同一模型下使用不同的数据集参数进行训练时 就需要多次输入一些相同类型的参数 从而造成时间的浪费 gin库就是为了统一化操作这些参数而出现的 它允许函数或类被注释为 gin configurable 这样就
  • 微信小程序(typescript) npm添加Tdesign UI组件库

    最近 发现一个新的微信小程序UI组件库 TDesign 腾讯自家出品 颜值杠杆 网址如下 https tdesign tencent com miniprogram getting started 安装 使用NPM Node js 安装包及
  • Java使用Aspose-Words实现Word转换Pdf

    一 在项目中引入Aspose Words依赖 下载地址 http pan baidu com s 1nvbJwnv 建议将jar包下载下来并上传到自己公司的私服里去
  • 【 OJ 】 HDOJ1052 贪心模拟田忌赛马 [ 46 ]

    转自 https www cnblogs com Open Source archive 2010 07 09 1904940 html 解题思路 贪心算法 根本思想是要让田忌花最小的代价来胜一每一场 让齐王花最大的代价来胜每一场 代价 可
  • 怎样用matlab产生泊松分布随机数

    random Poisson Lambda random Poisson Lambda m n 泊松分布的参数为Lambda 如果只产生一个随机数就是第一句的样子第二行的语句表示会产生m n个随机数 且这些随机数组成了m行n列的矩阵matl
  • C++基础知识 - 类模板与友元函数

    类模板与友元函数 Demo h pragma once template
  • SSM框架整合&配置环境&简单测试

    项目结构目录 第一步 导入ssm框架所需坐标 比如spring springmvc mybatis
  • 电子合同 数字签名项目记录

    项目页面 项目实现遇到的问题 在开发过程中遇到两个问题 前台 后台的签字展示大小和签字图片和合同原件合并的字体生成大小 签字生成的图片大小 最小化 不能是canvas画布的大小 第一个问题 针对第一个问题 如果不解决这个问题 在签字页面展示
  • Java学习之旅基础知识篇:面向对象之封装、继承及多态

    Java是一种面向对象设计的高级语言 支持继承 封装和多态三大基本特征 首先我们从面向对象两大概念 类和对象 也称为实例 谈起 来看看最基本的类定义语法 命名规则 类名 首字母大写 多个单词组合时每个单词首字母大写 单词之间不加任何连接符号
  • vue axios 阻塞未完成请求

    import from lodash import axios from axios const CancelToken Cancel axios const tokens 请求前处理 config 尽可能在最先注册的拦截器中调用 para
  • ThreeJS-3D教学一基础场景创建

    Three js 是一个开源的 JS 3D 图形库 用于创建和展示高性能 交互式的 3D 图形场景 它建立在 WebGL 技术之上 并提供了丰富的功能和工具 使开发者可以轻松地构建令人惊叹的 3D 可视化效果 Three js 提供了一套完
  • 深入完整的带你了解java对象的比较

    目录 元素的比较 1 基本类型的比较 2 对象比较的问题 1 运行结果 2 疑问 3 原因 对象的比较 1 覆写基类的equals 2 基于Comparble接口类的比较 3 基于比较器比较 4 三种方式对比 元素的比较 1 基本类型的比较