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

 

目录

元素的比较

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.rhkb.cn/news/99515.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

dockerfile的概念

目录 一.Dockerfile 概念 1.1 docker镜像的分层 二.Docker镜像的创建 2.1基于已有的镜像创建 2.2基于本地模板创建 2.3基于dockerfile创建 2.3.1dockerfile 结构(四部分) 三.Dockerfile操作指令 3.1ENTRYPOINT指令 3.2CMD 与entrypoint 四.ADD和copy区别 五.镜像分层的原…

Docker运行Nacos容器,过一会就报错`UnsatisfiedDependencyException`

Docker运行Nacos容器&#xff0c;过一会就报错UnsatisfiedDependencyException 问题背景&#xff1a; 最近要上线一个项目&#xff0c;由于要使用Nacos作为服务注册中心&#xff0c;为了方便&#xff0c;我就打算直接使用Docker部署Nacos&#xff0c;没想到Nacos启动没一会就嗝…

spring cloud 之 dubbo nacos整合

整体思路&#xff1a; 搭建本地nacos服务&#xff0c;详见docker安装nacos_xgjj68163的博客-CSDN博客 共三个工程&#xff0c;生产者服务、消费者服务、生产者和消费者共同依赖的接口工程&#xff08;打成jar&#xff0c;供生产者和消费者依赖&#xff09;&#xff1b; …

javaScript:常用的js字符串方法

目录 一.前言 二.字符串方法 1.charAt(num) 获取字符串指定位置上的字符 解释 示例 注意 2.length属性 获取字符串长度 解释 示例讲解 3.substring()字符串的截取 解释 特点 示例 4.slice()字符串截取 解释 特点 示例 应用 单行文本加省略号 字符串劫…

7-5 螺旋方阵

分数 20 全屏浏览题目 切换布局 作者 C课程组 单位 浙江大学 所谓“螺旋方阵”&#xff0c;是指对任意给定的N&#xff0c;将1到NN的数字从左上角第1个格子开始&#xff0c;按顺时针螺旋方向顺序填入NN的方阵里。本题要求构造这样的螺旋方阵。 输入格式&#xff1a; 输入在…

STM32 CubeMX (第一步Freertos任务管理:创建、删除、挂起、恢复)

STM32 CubeMX Freertos STM32 CubeMX &#xff08;Freertos任务&#xff1a;创建、删除、挂起、恢复&#xff09; STM32 CubeMX Freertos前言一、STM32 CubeMX 配置时钟树配置HAL时基选择TIM1&#xff08;不要选择滴答定时器&#xff1b;滴答定时器留给OS系统做时基&#xff09…

css学习1

1、样式定义如何显示元素。 2、样式通常保存至外部的css文件中。 3、样式可以使内容与表现分离。 4、css主要有两部分组成&#xff1a;选择器与一条或多条声明。 选择器通常为要改变的html元素&#xff0c;每条声明由一个属性和一个值组成。每个属性有一个值&#xff0c;属性…

网络通信原理UDP协议(第五十课)

UDP协议:用户数据包协议,无连接、不可靠,效率高 字段长度描述Source Port2字节标识哪个应用程序发送(发送进程)。Destination Port2字节标识哪个应用程序接收(接收进程)。Length2字节UDP首部加上UDP数据的字节数,最小为8。Checksum2字节覆盖UDP首部和UDP数据,是可…

[Docker] Windows 下基于WSL2 安装

Docker 必须部署在 Linux 内核的系统上。如果其他系统想部署 Docker 就必须安装一个虚拟 Linux 环境。 1. 开启虚拟化 进入系统BIOS&#xff08;AMD 为 SVM&#xff1b;Intel 为 Intel-vt&#xff09;改为启用(enable) 2. 开启WSL 系统设置->应用->程序和功能->…

浅拷贝与深拷贝

作者简介&#xff1a; zoro-1&#xff0c;目前大一&#xff0c;正在学习Java&#xff0c;数据结构等 作者主页&#xff1a; zoro-1的主页 欢迎大家点赞 &#x1f44d; 收藏 ⭐ 加关注哦&#xff01;&#x1f496;&#x1f496; 浅拷贝与深拷贝 浅拷贝浅拷贝定义浅拷贝代码演示浅…

《Linux运维总结:Centos7.6之OpenSSH7.4p1升级版本至9.4p1》

Centos通过yum升级OpenSSH 在官方支持更新的CentOS版本&#xff0c;如果出现漏洞&#xff0c;都会通过更新版本来修复漏洞。这时候直接使用yum update就可以升级版本。 yum -y update openssh 但是&#xff0c;CentOS更新需要有一段时间&#xff0c;不能在漏洞刚出来的时候就有…

最长公共子序列——力扣1143

解法:动态规划 int longestCommonSubsequence(string text1, string text2){int m=text1.size(), n=text2.size

【微服务】一文了解 Nacos

一文了解 Nacos Nacos 在阿里巴巴起源于 2008 2008 2008 年五彩石项目&#xff08;完成微服务拆分和业务中台建设&#xff09;&#xff0c;成长于十年双十一的洪峰考验&#xff0c;沉淀了简单易用、稳定可靠、性能卓越的核心竞争力。 随着云计算兴起&#xff0c; 2018 2018 20…

opencv进阶03-图像与鼠标的交互示例

在处理图像时&#xff0c;可能需要与当前正在处理的图像进行交互。OpenCV 提供了鼠标事件&#xff0c;使用户可以通过鼠标与图像交互。鼠标事件能够识别常用的鼠标操作&#xff0c;例如&#xff1a;针对不同按键的单击、双击&#xff0c;鼠标的滑动、拖曳等。 例如&#xff0c;…

【Windows系统编程】06.HotFixHook与进程通信(详解HotFixHook)

上一讲讲到的InlineHook&#xff0c;每次Hook的时候&#xff0c;都要读写两次内存&#xff08;先Hook&#xff0c;再还原&#xff09;这种Hook方式&#xff0c;性能比较低&#xff0c;今天我们讲的这种Hook方式&#xff0c;可以说是InlineHook的升级版本 HotFix&#xff08;热…

Android3:布局

一。线性布局 创建项目Linear Layout Example activity_main.xml <?xml version"1.0" encoding"utf-8"?><LinearLayout xmlns:android"http://schemas.android.com/apk/res/android"android:layout_width"match_parent"an…

‘VB6EXT.OLB’ could not be registered

打开VB6提示&#xff1a;‘VB6EXT.OLB’ could not be registered 解决办法&#xff1a; 用管理员打开。 实测可行。 参考&#xff1a;VB6 Error please help-VBForums

uni-app引入sortable列表拖拽,兼容App和H5,拖拽排序。

效果: 拖拽排序 背景&#xff1a; 作为一名前端开发人员&#xff0c;在工作中难免会遇到拖拽功能&#xff0c;分享一个github上一个不错的拖拽js库&#xff0c;能满足我们在项目开发中的需要&#xff0c;下面是我在uniapp中使用SortableJS的使用详细流程&#xff1b; vue开发…

TCP定制协议,序列化和反序列化

目录 前言 1.理解协议 2.网络版本计算器 2.1设计思路 2.2接口设计 2.3代码实现&#xff1a; 2.4编译测试 总结 前言 在之前的文章中&#xff0c;我们说TCP是面向字节流的&#xff0c;但是可能对于面向字节流这个概念&#xff0c;其实并不理解的&#xff0c;今天我们要介…

派森 #P122. 峰值查找

描述 给定一个长度为n的列表nums&#xff0c;请你找到峰值并返回其索引。数组可能包含多个峰值&#xff0c;在这种情况下&#xff0c;返回任何一个所在位置即可。 &#xff08;1&#xff09;峰值元素是指其值严格大于左右相邻值的元素。严格大于即不能有等于&#xff1b; &…