【Java SE】Java比较器:Comparable、Comparator

目录

1.前言

2.Comaprable接口

2.1 使用细节

2.2 案例演示

3.Comparator接口

3.1 为什么需要Comparator接口

3.2 使用细节

3.3 案例演示

4.Comparable、Comparator对比


1.前言

Java 中的对象,正常情况下,只能进行比较:==  或  != 。不能使用 >< 。但是在实际开发场景中,有时候需要对多个对象进行排序,言外之意,就是需要比较对象的大小。这便引出了 Comparable、Comparator 两个接口

2.Comaprable接口

Comparable 位于 java.lang.Comaprable,其源码如下:

package java.lang;
import java.util.*;
public interface Comparable<T> {public int compareTo(T o);
}

2.1 使用细节

实现 Comparable 接口的类必须实现 int compareTo(T o) 方法,两个对象可以通过 int compareTo(T o) 方法的返回值来比较大小:

        (1)当前对象 this 大于形参对象 o,则返回正整数

        (2)当前对象 this 小于形参对象 o,则返回负整数

        (3)当前对象 this 等于形参对象 o,则返回 0

 实现 Comparable 接口的对象列表或数组可以通过 Collections.sort Arrays.sort 进行自动排序,无需指定 Collection.sort(...)、Arrays.sort(...) 方法的第二个比较器参数,底层会根据类中实现的 int compareTo(T o)  作为排序逻辑

String、八大包装类implements 了该接口,并实现了 int compareTo(T o) 方法,都是从小到大排列的

String:按照字符串中字符的 ASCII 值进行比较
Character:按照字符的 ASCII 值来进行比较
数值类型对应的包装类以及 BigInteger、BigDecimal :按照它们对应的数值大小进行比较
Boolean:true 对应的包装类实例大于 false 对应的包装类实例
Date、Time等:后面的日期时间比前面的日期时间大

2.2 案例演示

案例1 :根据学生的年龄对学生类型数组进行升序排序 

import java.util.Arrays;
import java.util.Comparator;
public class demo {public static void main(String[] args) {Student s1 = new Student("小马", 100);Student s2 = new Student("蔡徐坤", 5);Student s3 = new Student("ftt", 90);Student[] arr1  = {s1,s2,s3};Student[] arr2  = {s1,s2,s3};System.out.println("排序前,所有学生:");Arrays.stream(arr1).forEach(student -> System.out.println(student));System.out.println("----------------------");//方式1:使用冒泡排序System.out.println("按照年龄排序:");for (int i = 1; i < arr1.length; i++) {for (int j = 0; j < arr1.length-i; j++) {if(arr1[j].compareTo(arr1[j+1])>0){Student temp = arr1[j];arr1[j] = arr1[j+1];arr1[j+1] = temp;}}}Arrays.stream(arr1).forEach(student -> System.out.println(student));System.out.println("----------------------");//方式2:使用Arrays.sort排序,因为在Student类已实现Comparable接口,所以无需指定比较器Arrays.sort(arr2);Arrays.stream(arr2).forEach(student -> System.out.println(student));}
}class Student implements Comparable<Student> {public String name;public int age;public Student(){}public Student(String name, int age) {this.name = name;this.age = age;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +'}';}//按学生年龄升序排序@Overridepublic int compareTo(Student anotherStudent) {if(this.age > anotherStudent.age){return 1;}else if(this.age < anotherStudent.age){return -1;}else{return 0;}}
}

 案例1运行结果:

案例2 :对字符数组进行排序

import java.util.Arrays;
public class demo {public static void main(String[] args) {Character[] arr = {'b','a','c','d'};System.out.println("排序前的字符数组:"+Arrays.toString(arr));Arrays.sort(arr);//Arrays底层会将Character类中实现的 int compareTo(T o) 方法作为排序逻辑System.out.println("排序后的字符数组:"+Arrays.toString(arr));}
}

 案例2运行结果: 

3.Comparator接口

Comparator 接口位于 java.until.Comparator 下,其中关于 int compareTo(...) 接口的源码如下:

package java.util;public interface Comparator<T>{int compare(T o1,T o2);
}

3.1 为什么需要Comparator接口

场景 ① :当只有第三方的类时(即只有 .class 字节码文件,没有 .java 源文件,无法修改代码),且这些类没有实现 java.lang.Comparable 接口

场景 ② :类中提前实现了 Comparable 接口,指定了两个对象比较大小的规则,但此时如果不想按照它预定义的方法比较大小,但是又不能随意修改源码,因为会影响其他地方的使用,怎么办呢?

因此,基于 ①、②Java 增加了一个 java.util.Comparator 接口来解决问题

3.2 使用细节

通常是用一个单独的其他的类来实现 Comparator 接口

② 实现 Comparator 的类必须实现 int compareTo (T o1,T o2) 方法,两个对象可以通过 int compareTo (T o1,T o2) 方法的返回值来比较大小:

        (1) o1 大于 o2,则返回正整数

        (2) o1 小于 o2,则返回负整数

        (3) o1 等于 o2,则返回 0

 在使用 Collection.sortArrays.sort 实现排序功能时,可以将实现了 Comparator 接口的类的实例传递给 Collection.sortArrays.sort,作为排序逻辑的比较器

3.3 案例演示

案例

import java.util.Arrays;
import java.util.Comparator;
public class demo {public static void main(String[] args) {//定义比较器实例StudentScoreComparator sc = new StudentScoreComparator();Student s1 = new Student("小马", 22,98);Student s2 = new Student("jack", 55,90);Student s3 = new Student("mary", 30,67);Student[] arr1  = {s1,s2,s3};Student[] arr2  = {s1,s2,s3};System.out.println("按分数排序前,所有学生:");Arrays.stream(arr1).forEach(student -> System.out.println(student));System.out.println("----------------------");//方式1:使用冒泡排序System.out.println("按照分数排序:");for (int i = 1; i < arr1.length; i++) {for (int j = 0; j < arr1.length-i; j++) {if(sc.compare(arr1[j],arr1[j+1]) > 0) {Student temp = arr1[j];arr1[j] = arr1[j+1];arr1[j+1] = temp;}}}Arrays.stream(arr1).forEach(student -> System.out.println(student));System.out.println("----------------------");//方式2:使用Arrays.sort排序,指定StudentScoreComparator为比较器,按学生的分数排序Arrays.sort(arr2,sc);Arrays.stream(arr2).forEach(student -> System.out.println(student));}
}//定制比较器类,按学生的分数升序排序
class StudentScoreComparator implements Comparator<Student>{@Overridepublic int compare(Student s1, Student s2) {if(s1.score > s2.score){return 1;}else if(s1.score < s2.score){return -1;}else{return 0;}}
}class Student implements Comparable<Student> {public String name;public int age;public int score;public Student(){}public Student(String name, int age, int score) {this.name = name;this.age = age;this.score = score;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +", score=" + score +'}';}//按学生年龄升序排序@Overridepublic int compareTo(Student anotherStudent) {if(this.age > anotherStudent.age){return 1;}else if(this.age < anotherStudent.age){return -1;}else{return 0;}}
}

案例1运行结果: 

4.Comparable、Comparator对比

ComparableComparator
实现位置类内部实现外部独立实现
排序规则数量只能定义一种排序规则可根据业务求定义多种排序规则
侵入性需要修改原类代码不需要修改原类代码
方法int compareTo (T o)int compare (T o1, T o2)
使用场景默认排序,如 Arrays.sort(arr)灵活排序,如 Arrays.sort(arr,comparator)

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

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

相关文章

(二)创建实例

在这节中&#xff0c; 创建一个实例初始化Vulkan库,指定驱动程序需要使用的应用程序信息 1&#xff0c;要有个实例句柄 VkInstance instance; 2&#xff0c;设置创建Vulkan驱动程序需要的信息&#xff0c; VkInstanceCreateInfo createInfo {}; createInfo.sType VK_STRUCTUR…

HCIP之VRRP

1. VRRP是什么 VRRP&#xff08;Virtual Router Redundancy Protocol&#xff0c;虚拟路由冗余协议&#xff09;是一种用于提高网络可靠性的容错协议。它通过将多台路由器虚拟成一台虚拟路由器&#xff0c;实现网关的冗余备份。当主路由器&#xff08;Master&#xff09;出现故…

高效内存管理:x86-64架构中的分页机制

在 x86-64 架构的世界里&#xff0c;内存分页机制扮演着举足轻重的角色&#xff0c;它就像是一座桥梁&#xff0c;连接着虚拟地址与物理地址。简单来说&#xff0c;内存分页机制就是将线性地址&#xff08;也就是虚拟地址&#xff09;切分成一个个固定大小的页&#xff0c;并把…

【软件工程】填空题

真题 2024-10 16.数据字典是用来定义_____中各个成分的具体含义的。 17.模块设计的基本原则是_____。 18.接口是操作的一个集合,其中每个操作描述了类、构件或子系统的一个_____。 19.耦合是指不同模块之间_____的度量。 20.RUP的突出特点是,它是一种以用况为驱动的、…

第二卷:海盐城血战(37-72回)正反人物群像

第二卷&#xff1a;海盐城血战&#xff08;37-72回&#xff09;正反人物群像 核心矛盾&#xff1a;寒门军事崛起 → 内部倾轧 → 制度性腐败 主题&#xff1a;通过人物群像展现寒门胜利的虚幻性与权力异化的必然性 一、正派阵营&#xff08;寒门抗争势力&#xff09; 1. 刘裕…

23_js面向对象

上次我们讲运动函数&#xff0c;实际开发不会写运动函数。只是讲一下思想。 现在讲一下用原生js去实现轮播图&#xff0c;引入到对象 首先&#xff0c;要明确 面向对象不是语法&#xff0c;是一个思想&#xff0c;是一种编程模式 面向&#xff1a;朝向 面向对象&#xff1a…

torch不能使用cuda的解决方案

遇到了这样的报错&#xff0c;说明 torch不能使用cuda 反思 我频繁地尝试安装不同的 nvdia 驱动&#xff0c;浪费了很多时间。因为我的错误地认为nvidia会自带cuda&#xff0c;其实cuda需要单独安装。 还有我的torch是cpu版本的&#xff0c;即使nvidia cuda安装了&#xff0…

kettle从入门到精通 第九十三课 ETL之kettle kettle 调用web service接口5种方法,一文彻底搞懂

场景&#xff1a;群里有小伙伴向我求助如何调用web service接口&#xff0c;趁着周末时间&#xff0c;给兄弟们搞demo。 1、本次使用的web service服务接口地址是http://ws.webxml.com.cn/WebServices/WeatherWS.asmx?opgetSupportCityDataset&#xff0c; 此接口根据用户输入…

蓝桥杯 14 天 十五届蓝桥杯 数字诗意

static boolean kkk(long x) {if(x1)return true;else {// 初始化xx为1&#xff0c;用于计算2的幂long xx 1;// 循环60次&#xff0c;检查2的幂是否等于xfor (int i 1; i < 60; i) {xx * 2; // 每次将xx乘以2if (xx x) { // 如果xx等于x&#xff0c;说明x是2的幂&#xf…

异常与捕获

1.C 异常概念 异常是一种处理错误的方式&#xff0c;当一个函数发现自己无法处理的错误时就可以抛出异常&#xff0c;让函数的直接或间接的调用者处理这个错误。 throw&#xff1a;当问题出现时&#xff0c;程序会抛出一个异常。这是通过使用 throw 关键字来完成的。catch&am…

2025年最新自动化/控制保研夏令营预推免面试真题分享(东南大学苏州校区/华东理工/南航/天大)

笔者来2021级本科自动化专业&#xff0c;以下部分将介绍我在夏令营以及预推免期间发生经历和问题 东南大学苏州校区蒙纳士大学联培 东南大学苏州校区的项目算是一个比较小众的项目&#xff0c;是第一年在苏州校区&#xff0c;二三年到南京校区找导师&#xff08;不提供住宿自…

【SQL】MySQL基础2——视图,存储过程,游标,约束,触发器

文章目录 1. 视图2. 存储过程2.1 创建存储过程2.2 执行存储过程 3. 游标4. 约束4.1 主键约束4.2 外键约束4.3 唯一约束4.4 检查约束 5. 触发器 1. 视图 视图是虚拟的表&#xff0c;它是动态检索的部分。使用视图的原因&#xff1a;避免重复的SQL语句&#xff1b;使用表的部分而…

OGG故障指南:OGG-01163 Bad column length (xxx) specified for column

报错 OGG-01163 Bad column length (xxx) specified for column AAA in table OWNER.TABLE, maximum allowable length is yyy原因 源端修改了字段长度。 虽然源端和目标端的长度已经通过DDL语句修改到一致&#xff0c;在extract进程未重启的情况下&#xff0c;生成的trail文…

Linux进程状态补充(10)

文章目录 前言一、阻塞二、挂起三、运行R四、休眠D五、四个重要概念总结 前言 上篇内容大家看的云里雾里&#xff0c;这实在是正常不过&#xff0c;因为例如 写实拷贝 等一些概念的深层原理我还没有讲解&#xff0c;大家不用紧张&#xff0c;我们继续往下学习就行&#xff01;&…

信息学奥赛一本通 1609:【例 4】Cats Transport | 洛谷 CF311B Cats Transport

【题目链接】 ybt 1609&#xff1a;【例 4】Cats Transport 洛谷 CF311B Cats Transport 【题目考点】 1. 动态规划&#xff1a;斜率优化动规 【解题思路】 解法1&#xff1a;设a点的前缀和 输入的 d d d序列是从 d 2 d_2 d2​到 d n d_n dn​&#xff0c;共n-1个数字。人…

bluecode-20240913_1_数据解码

时间限制&#xff1a;C/C 1000MS&#xff0c;其他语言 2000MS 内存限制&#xff1a;C/C 256MB&#xff0c;其他语言 512MB 难度&#xff1a;困难 数据解码 指定有一段经过编码的二进制数据&#xff0c;数据由0个或多个"编码单元"组成。"编码单元"的编码方式…

接口自动化进阶 —— Pytest全局配置pytest.ini文件详解!

pytest.ini 是 Pytest 的全局配置文件&#xff0c;用于自定义测试运行的行为和规则。通过配置 pytest.ini&#xff0c;可以避免在命令行中重复输入参数&#xff0c;提升测试的效率和一致性。 1. 配置文件的位置和格式 位置&#xff1a;pytest.ini 文件通常放在项目的根目录下。…

ModuleNotFoundError: No module named ‘demjson‘

错误 ModuleNotFoundError: No module named demjson 表明 Python 无法在其环境中找到名为 demjson 的模块。demjson 是一个第三方库&#xff0c;用于在 Python 中编码和解码 JSON 数据。如果你尝试导入它但遇到了这个错误&#xff0c;那很可能是因为你的 Python 环境中没有安装…

1、C51单片机(STC8G2K64S4)串口实验

一、串口1接线图 1、下面是单片机外接电路图&#xff0c;P30,P31分别用于RXD和TXD功能引脚 2、我们来查看单片机手册 串口1需要设置的寄存器 串口1的功能脚配置选择位&#xff0c;看电路图选择的是P3.0,P3.1。 3、串口1&#xff1a;SCON控制寄存器 设置为0x50:0101 0000。&a…

3PL EDI:SA Piper Logistics EDI需求分析

SA Piper Logistics成立于2005年&#xff0c;是一家专注于全球供应链管理的第三方物流服务商&#xff08;3PL&#xff09;&#xff0c;总部位于美国芝加哥。公司以“优化物流效率&#xff0c;重塑供应链价值”为使命&#xff0c;提供仓储管理、运输规划、订单履行及跨境清关等一…