Java——比较器
引入的背景
我们知道基本数据类型的数据(除boolean类型外)需要比较大小的话,直接使用比较运算符即可,但是引用数据类型是不能直接使用比较运算符来比较大小的。那么,如何解决这个问题呢?
在Java中经常会涉及到对象数组的排序问题,那么就涉及到对象之间的比较问题。
Java实现对象排序的方式有两种:
- 自然排序:java.lang.Comparable
- 定制排序:java.util.Comparator
自然排序:java.lang.Comparable
Comparable接口强行对实现它的每个类的对象进行整体排序。这种排序被称为类的自然排序。
实现 Comparable 的类必须实现 compareTo(Object obj) 方法,两个对象即通过 compareTo(Object obj) 方法的返回值来比较大小。
如果当前对象this大于形参对象obj,则返回正整数。
如果当前对象this小于形参对象obj,则返回负整数。
如果当前对象this等于形参对象obj,则返回零。
package java.lang;public interface Comparable{int compareTo(Object obj);
}
Comparable 的典型实现:(默认都是从小到大排列的)
- String:按照字符串中字符的Unicode值进行比较
- Character:按照字符的Unicode值来进行比较
- 数值类型对应的包装类以及BigInteger、BigDecimal:按照它们对应的数值大小进行比较
- Boolean:true 对应的包装类实例大于 false 对应的包装类实例
- Date、Time等:后面的日期时间比前面的日期时间大
测试String
代码示例:
@Testpublic void test1(){//测试String已经写好的String [] a = new String[]{"Jack", "Tom", "Lucy"};//排序之前for (int i = 0; i < a.length; i++) {System.out.print(a[i]+"\t");}System.out.println();//使用Arrays进行排序Arrays.sort(a);//排序之后进行展示for (int i = 0; i < a.length; i++) {System.out.print(a[i]+"\t");}}
运行效果:

测试自己实现comparable接口
Product类
package cn.edu.chd.exer1;import java.util.Objects;public class Product implements Comparable{private String name;private double prices;//无参构造public Product() {}//全参构造public Product(String name, double prices) {this.name = name;this.prices = prices;}public String getName() {return name;}public void setName(String name) {this.name = name;}public double getPrices() {return prices;}public void setPrices(double prices) {this.prices = prices;}@Overridepublic String toString() {return "Product{" +"name='" + name + '\'' +", prices=" + prices +'}';}@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Product product = (Product) o;return Double.compare(product.prices, prices) == 0 && name.equals(product.name);}@Overridepublic int hashCode() {return Objects.hash(name, prices);}@Overridepublic int compareTo(Object o) {//如果是同一个对象,return 0if (this == o){return 0;}//两个对象比较的标准是:价格从小到大,价格一样的话,按照名字从小到大if (o instanceof Product){Product p = (Product)o;int v = Double.compare(this.prices, p.prices);
// return v;if (v != 0){return v;}//价格如果相同,名字按照从小到大return this.name.compareTo(p.name);}//手动抛异常throw new RuntimeException("类型不匹配");}
}
测试
//对不同对象的大小进行排序@Testpublic void test2(){//商品数组Product[] products = new Product[5];//全参构造器,在new对象时就对属性进行赋值products[0] = new Product("Huawei", 5999);products[1] = new Product("XiaoMi", 4999);products[2] = new Product("iPhone", 9999);products[3] = new Product("vivo", 3999);products[4] = new Product("Honer", 5999);System.out.println("排序之前");//排序之前的遍历for (int i = 0; i < products.length; i++) {System.out.println(products[i]);}System.out.println("----------------------------------------------");//使用arrays进行排序Arrays.sort(products);System.out.println("排序之后");//排序后的遍历for (int i = 0; i < products.length; i++) {System.out.println(products[i]);}}
运行效果

定制排序:java.util.Comparator
思考
- 当元素的类型没有实现java.lang.Comparable接口而又不方便修改代码(例如:一些第三方的类,你只有.class文件,没有源文件)
- 如果一个类,实现了Comparable接口,也指定了两个对象的比较大小的规则,但是此时此刻我不想按照它预定义的方法比较大小,但是我又不能随意修改,因为会影响其他地方的使用,怎么办?(例如:我想要String按照字母从大到小的顺序排序,而不是默认的从小到大)
JDK在设计类库之初,也考虑到这种情况,所以又增加了一个java.util.Comparator接口。强行对多个对象进行整体排序的比较。
- 重写compare(Object o1,Object o2)方法,比较o1和o2的大小:如果方法返回正整数,则表示o1大于o2;如果返回0,表示相等;返回负整数,表示o1小于o2。
- 可以将 Comparator 传递给 sort 方法(如 Collections.sort 或 Arrays.sort),从而允许在排序顺序上实现精确控制。
Product类
package cn.edu.chd.exer2;import java.util.Objects;public class Product implements Comparable{private String name;private double prices;//无参构造public Product() {}//全参构造public Product(String name, double prices) {this.name = name;this.prices = prices;}public String getName() {return name;}public void setName(String name) {this.name = name;}public double getPrices() {return prices;}public void setPrices(double prices) {this.prices = prices;}@Overridepublic String toString() {return "Product{" +"name='" + name + '\'' +", prices=" + prices +'}';}@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Product product = (Product) o;return Double.compare(product.prices, prices) == 0 && name.equals(product.name);}@Overridepublic int hashCode() {return Objects.hash(name, prices);}@Overridepublic int compareTo(Object o) {//如果是同一个对象,return 0if (this == o){return 0;}//两个对象比较的标准是:价格从小到大,价格一样的话,按照名字从小到大if (o instanceof Product){Product p = (Product)o;int v = Double.compare(this.prices, p.prices);
// return v;if (v != 0){return v;}//价格如果相同,名字按照从小到大return this.name.compareTo(p.name);}//手动抛异常throw new RuntimeException("类型不匹配");}
}
按照商品的价格从低到高排序的comparator
@Testpublic void test1(){//new一个comparator接口的匿名实现类Comparator comparator = new Comparator() {//按照商品的价格从低到高排序@Overridepublic int compare(Object o1, Object o2) {if (o1 == o2){return 0;}if (o1 instanceof Product && o2 instanceof Product){//强转Product p1 = (Product) o1;Product p2 = (Product) o2;return Double.compare(p1.getPrices(), p2.getPrices());}throw new RuntimeException("类型不匹配");}};//商品数组Product[] products = new Product[5];//全参构造器,在new对象时就对属性进行赋值products[0] = new Product("Huawei", 5999);products[1] = new Product("XiaoMi", 4999);products[2] = new Product("iPhone", 9999);products[3] = new Product("vivo", 3999);products[4] = new Product("Honer", 5999);System.out.println("排序之前");//排序之前的遍历for (int i = 0; i < products.length; i++) {System.out.println(products[i]);}System.out.println("----------------------------------------------");//将comparator对象作为参数进行传入,排序Arrays.sort(products, comparator);System.out.println("排序之后");//排序后的遍历for (int i = 0; i < products.length; i++) {System.out.println(products[i]);}}
运行效果:

按照名称进行排序的comparator
//按照名称进行排序@Testpublic void test2(){//new一个comparator接口的匿名实现类Comparator comparator = new Comparator() {//按照商品的名称进行排序@Overridepublic int compare(Object o1, Object o2) {if (o1 == o2){return 0;}if (o1 instanceof Product && o2 instanceof Product){//强转Product p1 = (Product) o1;Product p2 = (Product) o2;return p1.getName().compareTo(p2.getName());}throw new RuntimeException("类型不匹配");}};//商品数组Product[] products = new Product[5];//全参构造器,在new对象时就对属性进行赋值products[0] = new Product("Huawei", 5999);products[1] = new Product("XiaoMi", 4999);products[2] = new Product("iPhone", 9999);products[3] = new Product("vivo", 3999);products[4] = new Product("Honer", 5999);System.out.println("排序之前");//排序之前的遍历for (int i = 0; i < products.length; i++) {System.out.println(products[i]);}System.out.println("----------------------------------------------");//将comparator对象作为参数进行传入,排序Arrays.sort(products, comparator);System.out.println("排序之后");//排序后的遍历for (int i = 0; i < products.length; i++) {System.out.println(products[i]);}}
运行效果:

相关文章:
Java——比较器
引入的背景 我们知道基本数据类型的数据(除boolean类型外)需要比较大小的话,直接使用比较运算符即可,但是引用数据类型是不能直接使用比较运算符来比较大小的。那么,如何解决这个问题呢? 在Java中经常会涉…...
【数据结构】初识泛型
文章目录 一般的类和方法,只能使用具体的类型: 要么是基本类型,要么是自定义的类。这种限制对代码的束缚就会很大。所以我们引入了泛型。泛型,泛顾名思义就是广泛的意思。就是适用于许多许多类型。从代码上讲,就是对类型实现了参数…...
代码随想录--哈希--有效的字母异位词
给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。 示例 1: 输入: s "anagram", t "nagaram" 输出: true 示例 2: 输入: s "rat", t "car" 输出: false 说明: 你可以假设字符串只包含小写字母。…...
MySQL——数据的增删改
2023.9.12 本章开始学习DML (数据操纵语言) 语言。相关学习笔记如下: #DML语言 /* 数据操作语言: 插入:insert 修改:update 删除:delete */#一、插入语句 #方式一:经典的插入 /* 语法: insert …...
云服务器与http服务器
如何与http服务器建立连接(客户端)? http请求设计格式: 例子: 发送http请求 http数据响应格式: 接收http服务器返回的数据需要进一步进行字符串处理操作,提取有用的数据。...
golang教程 beego框架笔记一
安装beego 安装bee工具 beego文档 # windos 推荐使用 go install github.com/beego/bee/v2master go get -u github.com/beego/bee/v2masterwindows使用安装bee工具时碰到的问题; 环境配置都没有问题,但是执行官网的命令:go get -u github…...
【深度学习】Mini-Batch梯度下降法
Mini-Batch梯度下降法 在开始Mini-Batch算法开始之前,请确保你已经掌握梯度下降的最优化算法。 在训练神经网络时,使用向量化是加速训练速度的一个重要手段,它可以避免使用显式的for循环,并且调用经过大量优化的矩阵计算函数库。…...
AI项目六:WEB端部署YOLOv5
若该文为原创文章,转载请注明原文出处。 一、介绍 最近接触网页大屏,所以就想把YOLOV5部署到WEB端,通过了解,知道了两个方法: 1、基于Flask部署YOLOv5目标检测模型。 2、基于Streamlit部署YOLOv5目标检测。 代码在…...
敲代码常用快捷键
1、代码拖动 PyCharm:按住 shiftalt鼠标选中某一区域来拖动,即可实现拖动这一区域至指定区域。Visual Studio Code (VSCode): - Windows/Linux:Alt 鼠标左键拖动 - MacOS:Option 鼠标左键拖动 IntelliJ IDEA: - Win…...
MyBatis: 分页插件PageHelper直接传递分页参数的用法
一、加分页插件依赖 <dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper-spring-boot-starter</artifactId><version>1.2.13</version></dependency>二、配置分页插件,并配置相关属性&a…...
Python基于Flask的高校舆情分析,舆情监控可视化系统
博主介绍:✌程序员徐师兄、7年大厂程序员经历。全网粉丝30W,Csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 运行效果图 基于Python的微博大数据舆情分析,舆论情感分析可视化系统 系统介绍 微博舆情分析系…...
Python第一次作业练习
题目分析: """ 参考学校的相关规定。 对于四分制,百分制中的90分及以上可视为绩点中的4分,80 分及以上为3分,70 分以上为2分,60 分以上为1分; 五分制中的5分为四分制中的4分,4分为3分&#…...
InstallShield打包升级时不覆盖原有文件的解决方案
一个.NET Framework的Devexpress UI Windows Form项目,用的InstallShield,前些个版本都好好的,最近几个版本突然就没法更新了,每次更新的时候都覆盖不了原文件,而且这样更新后第一次打开程序(虽然是老程序&…...
服务器巡检表-监控指标
1、巡检指标 系统资源K8S集群NginxJAVA应用RabbitMQRedisPostgreSQLElasticsearchELK日志系统 2、巡检项 检查项目 检查指标 检查标准 系统资源 CPU 使用率 正常:<70% 低风险:≥ 70% 中风险:≥ 85% 高风险:≥ 9…...
无涯教程-JavaScript - DDB函数
描述 DDB函数使用双倍余额递减法或您指定的某些其他方法返回指定期间内资产的折旧。 语法 DDB (cost, salvage, life, period, [factor])争论 Argument描述Required/OptionalCostThe initial cost of the asset.RequiredSalvage 折旧结束时的价值(有时称为资产的残值)。 该…...
uniapp打包微信小程序。报错:https://api.weixin.qq.com 不在以下 request 合法域名列表
场景:在进行打包上传测试时,发现登录失效,但在测试中【勾选不效应合法域名】就可以。 出现原因:我在获取到用户code后,直接使用调用官方接口换取openid 解决方案: 可以把code带给后端,让他们返…...
stm32之31.iic
iic双线制。一根是SCL,作为时钟同步线;一根是SDA,作为数据传输线 SDN #include "iic.h"#define SCL PBout(8)#define SDA_W PBout(9) #define SDA_R PBin(9)void IIC_GPIOInit(void) {GPIO_InitTypeDef GPIO_InitStructure;//使能时钟GR…...
新的 ChatGPT 提示工程技术:程序模拟
即时工程的世界在各个层面上都令人着迷,并且不乏巧妙的方法来推动像 ChatGPT 这样的代理生成特定类型的响应。思想链 (CoT)、基于指令、N-shot、Few-shot 等技术,甚至奉承/角色分配等技巧都是充满提示的库背后的灵感,旨在满足各种需求。 在本文中,我将深入研究一项技术,据…...
【Python】爬虫基础
爬虫是一种模拟浏览器实现,用以抓取网站信息的程序或者脚本。常见的爬虫有三大类: 通用式爬虫:通用式爬虫用以爬取一整个网页的信息。 聚焦式爬虫:聚焦式爬虫可以在通用式爬虫爬取到的一整个网页的信息基础上只选取一部分所需的…...
leetcode分类刷题:队列(Queue)(三、优先队列用于归并排序)
1、当TopK问题出现在多个有序序列中时,就要用到归并排序的思想了 2、将优先队列初始化为添加多个有序序列的首元素的形式,再循环K次优先队列的出队和出队元素对应序列下个元素的入队,就能得到TopK的元素了 3、这些题目好像没有TopK 大用小顶堆…...
数字电路小白也能懂:用Logisim搞定LED计数电路,从真值表到封装测试保姆级教程
数字电路零基础实战:用Logisim构建LED计数器的完整指南 从困惑到清晰:为什么选择Logisim作为数字电路入门工具 第一次接触数字电路时,面对密密麻麻的逻辑门和抽象的真值表,大多数初学者都会感到无从下手。传统教材中复杂的公式推导…...
Parabolic:简单高效的免费视频下载工具,yt-dlp图形界面终极方案
Parabolic:简单高效的免费视频下载工具,yt-dlp图形界面终极方案 【免费下载链接】Parabolic Download web video and audio 项目地址: https://gitcode.com/GitHub_Trending/pa/Parabolic 还在为寻找一款既强大又易用的视频下载工具而烦恼吗&…...
https://github.com/langgenius/dify查看设置的apikey
现在我已经掌握了足够的信息,来做一个完整清晰的分析。好的,现在我来给出一个完整的分析。 Dify provider_model_credentials.encrypted_config 解密分析 整体加密架构 Dify 使用 PKCS1_OAEP 加密来保护 API key。每个用户(tenant)…...
各高校论文AI率标准差异解读:从10%到30%不同学校标准差距2026年免费达标方案
各高校论文AI率标准差异解读:从10%到30%不同学校标准差距2026年免费达标方案 关于高校论文AI率标准解读,我系统研究过一段时间,也实际验证过各种说法。 这篇文章把关键的逻辑理清楚——知道了原理,遇到问题就知道该怎么处理了。…...
S18|Worktree 隔离:多 Agent 平台 —— 独立目录,独立车道,让并行工作互不干扰
在前十七章,我们的 Agent 已经拥有循环、工具、计划、子代理、技能、压缩、权限、Hook、记忆、提示词流水线、错误恢复、任务系统、后台任务、定时调度、多 Agent 团队、团队协议、自主代理十七大核心能力,能拆任务、认领任务、让多个 Agent 并行推进不同…...
【UEFI实战】GOP协议详解:从模式查询到像素操作
1. GOP协议基础:UEFI图形显示的核心机制 第一次接触UEFI图形编程时,我被屏幕上突然出现的红色进度条震撼到了——原来在系统启动的早期阶段就能实现图形化显示。这背后的关键就是EFI_GRAPHICS_OUTPUT_PROTOCOL(简称GOP)࿰…...
【权威发布】Midjourney V6结构提示词标准白皮书(含官方未公开的4类语法优先级矩阵与37个避坑节点)
更多请点击: https://intelliparadigm.com 第一章:Midjourney V6结构提示词的核心演进与范式变革 Midjourney V6 标志着生成式图像模型在语义理解与结构化表达上的重大跃迁。其提示词(prompt)系统不再仅依赖关键词堆叠࿰…...
基于MCP协议的Claude对话历史管理工具:架构、配置与实战
1. 项目概述:一个为Claude桌面应用量身定制的历史记录管理工具如果你和我一样,是Claude桌面应用的深度用户,那你一定对那个内置的对话历史管理功能颇有微词。它太基础了,基础到几乎只能算是一个“查看器”。想按日期、按项目、按关…...
3分钟搞定AI短视频:零门槛创作神器完全指南
3分钟搞定AI短视频:零门槛创作神器完全指南 【免费下载链接】MoneyPrinterTurbo 利用AI大模型,一键生成高清短视频 Generate short videos with one click using AI LLM. 项目地址: https://gitcode.com/GitHub_Trending/mo/MoneyPrinterTurbo 还…...
告别裸机轮询:在STM32F103上为AHT20温湿度采集加入FreeRTOS实时任务管理
从裸机轮询到RTOS任务管理:STM32F103与AHT20温湿度传感器的架构升级实战 在嵌入式开发领域,如何从简单的功能实现进阶到健壮的软件架构设计,是每个开发者必须面对的挑战。本文将带你完成一次典型的架构升级——将基于STM32F103的AHT20温湿度传…...
