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 大用小顶堆…...

label-studio的使用教程(导入本地路径)
文章目录 1. 准备环境2. 脚本启动2.1 Windows2.2 Linux 3. 安装label-studio机器学习后端3.1 pip安装(推荐)3.2 GitHub仓库安装 4. 后端配置4.1 yolo环境4.2 引入后端模型4.3 修改脚本4.4 启动后端 5. 标注工程5.1 创建工程5.2 配置图片路径5.3 配置工程类型标签5.4 配置模型5.…...
反向工程与模型迁移:打造未来商品详情API的可持续创新体系
在电商行业蓬勃发展的当下,商品详情API作为连接电商平台与开发者、商家及用户的关键纽带,其重要性日益凸显。传统商品详情API主要聚焦于商品基本信息(如名称、价格、库存等)的获取与展示,已难以满足市场对个性化、智能…...

VB.net复制Ntag213卡写入UID
本示例使用的发卡器:https://item.taobao.com/item.htm?ftt&id615391857885 一、读取旧Ntag卡的UID和数据 Private Sub Button15_Click(sender As Object, e As EventArgs) Handles Button15.Click轻松读卡技术支持:网站:Dim i, j As IntegerDim cardidhex, …...

2025年能源电力系统与流体力学国际会议 (EPSFD 2025)
2025年能源电力系统与流体力学国际会议(EPSFD 2025)将于本年度在美丽的杭州盛大召开。作为全球能源、电力系统以及流体力学领域的顶级盛会,EPSFD 2025旨在为来自世界各地的科学家、工程师和研究人员提供一个展示最新研究成果、分享实践经验及…...

【网络安全产品大调研系列】2. 体验漏洞扫描
前言 2023 年漏洞扫描服务市场规模预计为 3.06(十亿美元)。漏洞扫描服务市场行业预计将从 2024 年的 3.48(十亿美元)增长到 2032 年的 9.54(十亿美元)。预测期内漏洞扫描服务市场 CAGR(增长率&…...
Qwen3-Embedding-0.6B深度解析:多语言语义检索的轻量级利器
第一章 引言:语义表示的新时代挑战与Qwen3的破局之路 1.1 文本嵌入的核心价值与技术演进 在人工智能领域,文本嵌入技术如同连接自然语言与机器理解的“神经突触”——它将人类语言转化为计算机可计算的语义向量,支撑着搜索引擎、推荐系统、…...
3403. 从盒子中找出字典序最大的字符串 I
3403. 从盒子中找出字典序最大的字符串 I 题目链接:3403. 从盒子中找出字典序最大的字符串 I 代码如下: class Solution { public:string answerString(string word, int numFriends) {if (numFriends 1) {return word;}string res;for (int i 0;i &…...
适应性Java用于现代 API:REST、GraphQL 和事件驱动
在快速发展的软件开发领域,REST、GraphQL 和事件驱动架构等新的 API 标准对于构建可扩展、高效的系统至关重要。Java 在现代 API 方面以其在企业应用中的稳定性而闻名,不断适应这些现代范式的需求。随着不断发展的生态系统,Java 在现代 API 方…...
前端中slice和splic的区别
1. slice slice 用于从数组中提取一部分元素,返回一个新的数组。 特点: 不修改原数组:slice 不会改变原数组,而是返回一个新的数组。提取数组的部分:slice 会根据指定的开始索引和结束索引提取数组的一部分。不包含…...

[论文阅读]TrustRAG: Enhancing Robustness and Trustworthiness in RAG
TrustRAG: Enhancing Robustness and Trustworthiness in RAG [2501.00879] TrustRAG: Enhancing Robustness and Trustworthiness in Retrieval-Augmented Generation 代码:HuichiZhou/TrustRAG: Code for "TrustRAG: Enhancing Robustness and Trustworthin…...