Java对象的比较

目录

PriorityQueue中插入对象

元素的比较

基本类型的比较

对象比较问题

 对象的比较

覆写基类的equals

基于Comparble接口类的比较

基于比较器的比较

三种方式的对比

集合框架中PriorityQueue的比较方式


PriorityQueue中插入对象

上一篇博文中我们讲了优先级队列,优先级队列插入元素时有个要求:插入的元素不能是null或者元素之间必须能够进行比较,为了简单起见,我们只是插入了Integer类型,那优先级队列中能否插入自定义类型对象呢?

来看下面这个例子:

class Student {public int age;//年龄public String name;//姓名public Student(int age, String name) {this.age = age;this.name = name;}
}public class TestPriorityQueue {public static void TestPriorityQueue(){PriorityQueue<Student> p = new PriorityQueue<>();p.offer(new Student(18, "lisi"));p.offer(new Student(6, "wangwu"));}public static void main(String[] args) {TestPriorityQueue();}
}

你会发现这样的运行结果:

出现这种情况是因为优先队列底层使用堆,而向堆中插入元素时,为了满足堆的性质,必须要进行元素的比较,而此时Student是没有办法直接进行比较的,因此抛出异常。 

元素的比较

基本类型的比较

在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);}
}

对象比较问题

class Student {public int age;//年龄public String name;//姓名public Student(int age, String name) {this.age = age;this.name = name;}
}public class TestPriorityQueue {public static void main(String[] args) {Student s1 = new Student(18, "lisi");Student s2 = new Student(6, "wangwu");Student s3 = s1;//System.out.println(s1 > s2); 编译报错System.out.println(s1 == s2);//编译成功->打印false,因为它们指向的是不同对象//System.out.println(s1 < s2); 编译报错System.out.println(s1 == s2);//编译成功->打印true,因为s1和s3指向的是同一对象}
}

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

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

//Object中equal的实现,可以看到:直接比较的是两个引用变量的地址
public boolean equals(Object obj) {return (this == obj);
}

 对象的比较

有些情况下,需要比较的是对象的内容,比如:向优先级队列中插入某个对象时,需要对按照对象中的内容来调整堆,那该如何处理呢?有以下几种方法:

覆写基类的equals

代码如下:

class Student {public int age;//年龄public String name;//姓名public Student(int age, String name) {this.age = age;this.name = name;}}@Overridepublic boolean equals(Object o) {//自己和自己比较if(this == o) {return true;//指向一个对象则返回true}//o如果是null对象,或者o不是Student的子类if(o == null || !(o instanceof Student)) {return false;}//注意基本类型可以直接比较,但引用类型最好调用其equal方法Student c = (Student)o;return age == c.age && name.equals(c.name);}

注意:一般覆写equals的套路如上

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

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

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

4.按照类的实现目标完成比较,例如这里只要年龄和姓名一样,就认为是相同的学生

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

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

基于Comparble接口类的比较

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

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

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

使用举例:

public class Student implements Comparable<Student> {public int age;public String name;public Student(int age, String name) {this.age = age;this.name = name;}//根据年龄比较,不管姓名//这里我们认为null是最小的@Overridepublic int compareTo(Student o) {if(o == null) {return 1;}return age - o.age;}public static void main(String[] args) {Student s1 = new Student(18, "lisi");Student s2 = new Student(6, "wangwu");Student s3 = new Student(18, "wangwu");System.out.println(s1.compareTo(s3));//==0System.out.println(s1.compareTo(s2));//>0System.out.println(s2.compareTo(s1));//<0}
}

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

基于比较器的比较

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

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

​
public interface Comparator<T> {//返回值//<0:表示o1指向的对象小于o2指向的对象//==0:表示o1指向的对象等于o2指向的对象//>0:表示o1指向的对象大于o2指向的对象int compare(T o1, T o2);
}​

注意:区分Comparable和Comparator. 

覆写Comparator中的compare方法

代码如下:

class Student {public int age;//年龄public String name;//姓名public Student(int age, String name) {this.age = age;this.name = name;}
}public class StudentComparator implements Comparator<Student> {//根据年龄比较,不管姓名//这里我们认为null是最小的@Overridepublic int compare(Student o1, Student o2) {if(o1 == o2) {return 0;}if(o1 == null) {return -1;}if(o2 == null) {return 1;}return o1.age - o2.age;}public static void main(String[] args) {Student p = new Student(18, "lisi");Student q = new Student(6, "wangwu");Student o = new Student(18, "wangwu");//定义比较器对象StudentComparator comparator = new StudentComparator();//使用比较器对象进行比较System.out.println(comparator.compare(p, o));System.out.println(comparator.compare(p, q));System.out.println(comparator.compare(q, p));}
}

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

三种方式的对比

覆写的方法说明
Object.equals因为所有类都是继承自Object的,所以直接覆写即可,不过只能比较相等与否
Comparable.compareTo需要手动实现接口,侵入性比较强,但一旦实现,每次用该类都有顺序,属于内部顺序
Comparator.compare需要实现一个比较器对象,对待比较类的侵入性弱,但对算法代码实现侵入性强

集合框架中PriorityQueue的比较方式

集合框架中的PriorityQueue底层使用堆结构,因此其内部的元素必须要能够比较大小,Priority采用了:Comparble和Comparator两种方式。

1.Comparable是默认的内部比较方式,如果用户插入自定义类型对象时,该类对象必须要实现Comparable接口,并覆写compareTo方法。

2.用户也可以选择使用比较器对象,如果用户插入自定义类型对象时,必须要提供一个比较器类,让该类实现Comparator接口并覆写compare方法。

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

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

相关文章

虚幻引擎:数据表格的C++常用API

1.将数据表格中的所有数据存到一个数组中 //参数1 // 错误提示 //参数2 // 存储的数组 TArray<FKeyInfoHeader*> array; KeyInfoDT->GetAllRows<FKeyInfoHeader>(TEXT("错误"),array); 2.获取表格中所有的行名称 TArray<FName>array; …

golang 拉取 bitbucket.org 私有库

以 bitbucket.org 平台和mac电脑为例 前置条件私库需要给你账号权限&#xff0c;可拉取的权限&#xff0c;否则无法进行正常拉取 我们采用ssh方式&#xff0c;需要在本地生成对应的 rsa 的公钥和私钥&#xff0c;将公钥配置如下图&#xff1a; 在 .ssh/config 写入你的配置 H…

2015架构案例(五十一)

第5题 【说明】某信息技术公司计划开发一套在线投票系统&#xff0c;用于为市场调研、信息调查和销售反馈等业务提供服务。该系统计划通过大量宣传和奖品鼓励的方式快速积累用户&#xff0c;当用户规模扩大到一定程度时&#xff0c;开始联系相关企业提供信息服务&#xff0c;并…

Codeforces Round 903 (Div. 3) C(矩形旋转之后对应的坐标)

题目链接&#xff1a;Codeforces Round 903 (Div. 3) C 题目&#xff1a; 思想&#xff1a; 旋转之后对应的坐标&#xff1a; &#xff08;i&#xff0c;j&#xff09;&#xff08;n1-j&#xff0c;i&#xff09;&#xff08;n1-i&#xff0c;n1-j&#xff09;&#xff08;j…

浅谈MDK, IAR,CLANG和GCC的局部变量字节对齐处理差异(2023-10-13)

视频&#xff1a; https://www.bilibili.com/video/BV1CB4y1Z7kA 浅谈MDK, IAR, CLANG和GCC的局部变量字节对齐处理差异 问题由来&#xff1a; 早期这个帖子里面的局部变量对齐仅测试了MDK AC5&#xff0c;但项目中使用AC6发现了新问题&#xff0c;看来AAPCS规约研究的还是不…

ArcGIS笔记4_水动力模型验证不理想时如何修改局部水深地形

本文目录 前言Step 1 模型验证不理想的情况Step 2 修改确值点并重新插值 前言 本章主要服务于MIKE水动力模型的调整修改工作。水动力模型跑完之后&#xff0c;常常会出现验证结果不理想的情况&#xff0c;比如潮位验证中&#xff0c;实测站点数据与模拟数据相差很大&#xff0…

苹果ios用户下载ipa文件内测签名的后的app应用下载安装到手机图标消失了-解决方案

下载好的应用竟然找不到了&#xff1f;这么神奇&#xff1f;我尝试了解了一下复原了同学给我的内容果然出现了我尝试科技了一下&#xff0c;总结了以下的可能性&#xff01;同学如果这个回答解决了你的困扰&#xff0c;同学给个赞&#xff0c;如果你有更好的排查方案评论区分享…

Modelsim查看波形窗口内断言(SVA)消息指示器

步骤1&#xff1a;创建工程并编译完成 在相应目录下创建好工程并编译无错误后&#xff1b; 步骤二&#xff1a; 在菜单栏中选择“Simulate”—>“Start Simulation”—>“Others”,在“Others Vsim Options”中输入 -msgmode both -displaymsgmode both 步骤三&#xf…

UI自动化测试 —— Jenkins配置

前一段时间帮助团队搭建了UI自动化环境&#xff0c;这里将Jenkins环境的一些配置分享给大家。 背景&#xff1a; 团队下半年的目标之一是实现自动化测试&#xff0c;这里要吐槽一下&#xff0c;之前开发的测试平台了&#xff0c;最初的目的是用来做接口自动化测试和性能测试&…

SQL Server远程登录失败

SQL Server远程登录失败 检查SQL SERVER 是否允许远程访问. 具体步骤: 1)在远端SQL Server主机上,打开SSMS并连接数据库 2)在相应”数据库”上单击右键,选择”属性” 3)选择”连接”选项卡,检查”远程服务器连接”下,RPC服务是否选择. 设置SQL Server相关TCP连接 1.打开SQL Se…

下载Python的不同版本在同一台电脑上如何共存

1. 下载安装不同版本的Python 官网下载&#xff1a;https://www.python.org/downloads/安装自己需要的版本&#xff08;我这里以Python3.6和Python3.9为例&#xff0c;下载安装细节不过多赘述&#xff09; &#xff08;这里的安装路径自己设定&#xff0c;命名最好是根据下载…

491. 递增子序列

给你一个整数数组 nums &#xff0c;找出并返回所有该数组中不同的递增子序列&#xff0c;递增子序列中 至少有两个元素 。你可以按 任意顺序 返回答案。 数组中可能含有重复元素&#xff0c;如出现两个整数相等&#xff0c;也可以视作递增序列的一种特殊情况。 示例 1&#x…

【160】相交链表

方法一&#xff1a;双指针法 算法思想&#xff1a; 使用两个指针p1&#xff0c;p2分别遍历headA和headB。 当p1遍历完headA或p2遍历完headB&#xff0c;我们让该指针去遍历另一个链表。 由于两个指针走的路程相同&#xff0c;所以若两链表相交&#xff0c;则p1&#xff0c;p2一…

项目管理之六大目标及成功方程式

项目管理的六大目标分别是范围、质量、时间、成本、收益和风险。在项目开始之前&#xff0c;需要明确了解项目的范围&#xff0c;并在项目执行过程中对范围进行严格控制&#xff0c;确保项目不偏离既定的范围。同时&#xff0c;需要明确项目的质量标准和预期成果&#xff0c;然…

VRTK4 代码 取消/禁用 抓取

using Tilia.Interactions.Interactables.Interactors;private InteractableFacade interactableFacade GetComponentInChildren<InteractableFacade>();//取消抓取 if (interactableFacade.IsGrabbed) {interactableFacade.UngrabAll(); } //禁用抓取功能 interactable…

Spring Boot:Dao层-实例介绍

目录 Dao层的作用Dao层的特点与 Service 层和 Controller 层的关系实例介绍MenuDaoOperatorLogDaoRoleDaoUserDao四个文件的共同点引用的包使用Repository注解继承JpaRepository接口接口的实体类的主键类型使用 Query()注解 Dao层的作用 负责与数据库进行交互&#xff0c;主要…

使用 Apache Kafka 进行发布-订阅通信中的微服务

发布-订阅消息系统在任何企业架构中都发挥着重要作用&#xff0c;因为它可以实现可靠的集成&#xff0c;而无需紧密耦合应用程序。在解耦的系统之间共享数据的能力并不是一个容易解决的问题。 考虑一家拥有多个使用不同语言和平台独立构建的应用程序的企业。它需要响应地共享数…

redis知识点整合

Redis是一种开源的内存数据结构存储系统&#xff0c;常用于缓存、消息队列、数据存储等场景。以下是Redis的一些常见知识点整合&#xff1a; 1. 数据结构&#xff1a;Redis支持多种数据结构&#xff0c;包括字符串、哈希表、列表、集合、有序集合等&#xff0c;每种数据结构都…

发个地区和对应的价格方案

在当今数字化的世界中&#xff0c;网络工程师面临着各种挑战&#xff0c;从跨界电商到爬虫&#xff0c;从出海业务到网络安全&#xff0c;再到游戏领域。为了应对这些挑战&#xff0c;网络工程师需要了解并利用各种技术&#xff0c;其中Socks5代理和代理IP技术成为了他们的得力…

FLAME模型运行原理

FLAME模型利用了线性蒙皮技术(linear blend skinning)来使面部网格随着姿态变形。 θ 参数的影响 FLAME建立了一个面部网格模板mesh T。确定了关键的面部关节点J,如颈部、下巴等关节。每个网格顶点都赋予了一个蒙皮权重W,表示它受每个关节的影响程度。在变形时,对每个关节按照…