Java高效编程(14):考虑实现 `Comparable
解锁Python编程的无限可能:《奇妙的Python》带你漫游代码世界
与其他方法不同,compareTo 并非 Object 类中声明的,而是 Comparable 接口的唯一方法。compareTo 方法与 equals 类似,但它不仅支持相等性比较,还允许顺序比较,同时它是泛型的。通过实现 Comparable 接口,一个类表明其实例具有自然顺序。这使得对实现 Comparable 的对象数组进行排序变得非常简单:
Arrays.sort(a);
使用 Comparable 接口,可以轻松地搜索、计算极值或维护自动排序的集合。例如,以下程序利用 String 实现了 Comparable,它打印出一个按字母顺序排列的命令行参数列表,并去除重复项:
public class WordList {public static void main(String[] args) {Set<String> s = new TreeSet<>();Collections.addAll(s, args);System.out.println(s);}
}
通过实现 Comparable,你的类可以与依赖该接口的各种通用算法和集合实现进行互操作。实现 Comparable 所需的工作量非常小,但却带来了巨大的收益。几乎所有 Java 平台库中的值类以及所有枚举类型(详见【条目34】)都实现了 Comparable。如果你编写的值类有明显的自然排序,例如字母顺序、数字顺序或时间顺序,那么你应该实现 Comparable 接口。
Comparable 接口声明如下:
public interface Comparable<T> {int compareTo(T t);
}
compareTo 方法的通用合同
compareTo 方法的通用合同类似于 equals 的合同:
- 比较当前对象与指定对象的顺序,返回负整数、零或正整数,分别表示当前对象小于、等于或大于指定对象。
- 如果两个对象具有不同类型,通常会抛出
ClassCastException。
这个合同的数学符号表示如下:
- 对所有
x和y,应确保sgn(x.compareTo(y)) == -sgn(y.compareTo(x)),这意味着x.compareTo(y)只有在y.compareTo(x)抛出异常时才会抛出异常。 - 应确保传递性:如果
x.compareTo(y) > 0 && y.compareTo(z) > 0,则x.compareTo(z) > 0。 - 如果
x.compareTo(y) == 0,则sgn(x.compareTo(z)) == sgn(y.compareTo(z))对所有z应成立。
此外,推荐但不强制要求 x.compareTo(y) == 0 等价于 x.equals(y)。如果违背了这一点,应在类文档中注明该类的自然顺序与 equals 不一致。
比较与 equals 的一致性
compareTo 方法的比较应符合 equals 的等价性、对称性和传递性原则。如果违反这些原则,可能会导致依赖比较的类(如 TreeSet、TreeMap)出错。虽然不致命,但会导致结果不一致。例如,BigDecimal 类的 compareTo 方法与其 equals 方法不一致。对于 HashSet,new BigDecimal("1.0") 和 new BigDecimal("1.00") 被视为不相等,而在 TreeSet 中则视为相等。
编写 compareTo 方法
编写 compareTo 方法类似于编写 equals 方法,但有一些关键区别。由于 Comparable 是参数化接口,因此 compareTo 方法是静态类型化的,避免了类型检查和强制转换。如果参数类型错误,代码甚至无法编译。
在 compareTo 方法中,字段是按顺序比较的。对于对象引用字段,可以递归调用 compareTo 方法。如果字段没有实现 Comparable,或者需要非标准排序,可以使用 Comparator。例如,下面是一个比较 CaseInsensitiveString 类的 compareTo 方法:
// 使用对象引用字段的单字段 Comparable
public final class CaseInsensitiveString implements Comparable<CaseInsensitiveString> {public int compareTo(CaseInsensitiveString cis) {return String.CASE_INSENSITIVE_ORDER.compare(s, cis.s);}// 其他代码省略
}
使用比较器构造方法实现 compareTo
在 Java 8 中,Comparator 接口提供了一组构造方法来简洁地构建比较器。下面是使用比较器构造方法实现 PhoneNumber 类 compareTo 的例子:
// 使用比较器构造方法的 Comparable
private static final Comparator<PhoneNumber> COMPARATOR =comparingInt((PhoneNumber pn) -> pn.areaCode).thenComparingInt(pn -> pn.prefix).thenComparingInt(pn -> pn.lineNum);public int compareTo(PhoneNumber pn) {return COMPARATOR.compare(this, pn);
}
这种方法通过使用 Comparator 的 comparingInt 和 thenComparingInt 方法来简洁地构建比较逻辑。
避免基于差值的比较器
不要使用基于两个值差值的比较器,例如:
// 错误的差值比较器 - 违反传递性
static Comparator<Object> hashCodeOrder = new Comparator<>() {public int compare(Object o1, Object o2) {return o1.hashCode() - o2.hashCode();}
};
这种方法容易受到整数溢出和浮点运算误差的影响。相反,应该使用静态比较方法或比较器构造方法,例如:
// 基于静态比较方法的比较器
static Comparator<Object> hashCodeOrder = new Comparator<>() {public int compare(Object o1, Object o2) {return Integer.compare(o1.hashCode(), o2.hashCode());}
};
或:
// 基于比较器构造方法的比较器
static Comparator<Object> hashCodeOrder = Comparator.comparingInt(o -> o.hashCode());
总结
当你实现具有合理顺序的值类时,应该让该类实现 Comparable 接口,以便能够轻松排序、搜索和在集合中使用。避免在 compareTo 方法中使用 < 和 > 操作符,推荐使用 Java 提供的静态比较方法或比较器构造方法。
相关文章:
Java高效编程(14):考虑实现 `Comparable
解锁Python编程的无限可能:《奇妙的Python》带你漫游代码世界 与其他方法不同,compareTo 并非 Object 类中声明的,而是 Comparable 接口的唯一方法。compareTo 方法与 equals 类似,但它不仅支持相等性比较,还允许顺序…...
华为昇腾CANN训练营2024第二季--Ascend C算子开发能力认证(中级)题目和经验分享
大家好,我是刘明,明志科技创始人,华为昇思MindSpore布道师。 技术上主攻前端开发、鸿蒙开发和AI算法研究。 努力为大家带来持续的技术分享,如果你也喜欢我的文章,就点个关注吧 正文开始 华为昇腾CANN训练营2024第二季…...
实战OpenCV之形态学操作
基础入门 形态学操作是一种基于图像形状的处理方法,主要用于结构分析,比如:边缘检测、轮廓提取、噪声去除等。这些操作通常使用一个称为“结构元素”(Structuring Element)的核来进行,结构元素可以是任何形状,但最常见的有矩形和圆形。形态学操作的核心在于通过结构元素…...
矩阵的特征值和特征向量
矩阵的特征值和特征向量是线性代数中非常重要的概念,用于描述矩阵对向量的作用,特别是在矩阵对向量的线性变换中的表现。它们帮助我们理解矩阵在某些方向上的缩放或旋转效果。 1. 特征值和特征向量的定义: 给定一个 n n n \times n nn 的…...
(11)MATLAB莱斯(Rician)衰落信道仿真2
文章目录 前言一、莱斯衰落信道仿真模型二、仿真代码与结果1.仿真代码2.仿真结果画图 三、后续:四、参考文献: 前言 首先给出莱斯衰落信道仿真模型,该模型由直射路径分量和反射路径分量组成,其中反射路径分量由瑞利衰落信道模型构…...
ComfyUI局部重绘换衣讲解
一、下载插件 ComfyUI-Impact-Pack 下载地址 https://github.com/ltdrdata/ComfyUI-Impact-Pack 主要用到sam Detector去绘制衣服蒙版和高斯模糊蒙版,高斯模糊让蒙版边缘更加柔和 sams模型 放在E:\Comfyui\ComfyUI\models\sams二、换衣思路 文生图或直接上传…...
Android——添加联系人
概述 方式一:使用ContentResolver多次写入,每次写入一个字段 第一步 往手机联系人应用中的raw_contacts表添加一条记录 raw_contacts表 ContentValues values new ContentValues();// 往 raw_contacts 添加联系人记录,并获取添加后的联…...
高级 Java Redis 客户端 有哪些?
高级Java Redis客户端主要包括以下几种: 1. Redisson (https://github.com/redisson/redisson) 特点:Redisson是一个在Redis的基础上实现的Java驻留数据网格(In-Memory Data Grid)。它不仅是一个Redis的J…...
jenkins项目发布基础
随着软件开发需求及复杂度的不断提高,团队开发成员之间如何更好地协同工作以确保软件开发的质量已经慢慢成为开发过程中不可回避的问题。Jenkins 自动化部署可以解决集成、测试、部署等重复性的工作,工具集成的效率明显高于人工操作;并且持续集成可以更早的获取代码变更的信息,…...
前缀和算法详解
对于查询区间和的问题,可以预处理出来一个前缀和数组 dp,数组中存储的是从下标 0 的位置到当前位置的区间和,这样只需要通过前缀和数组就可以快速的求出指定区间的和了,例如求 l ~ r 区间的和,就可以之间使用 dp[l - 1…...
Android-Handle消息传递和线程通信
本文为作者学习笔记,如有误,请各位大佬指点 目录 一、同步异步 二、Java多线程通信 三、Handler是什么 四、Handler相关的类 五、Handler常用方法 1. 发送消息 2. 接收处理消息 3. 切换线程 六、使用Handler 使用Handler更新UI 使用Handler延…...
【Kubernetes】常见面试题汇总(四十七)
目录 106.考虑一种情况,公司希望通过保持最低成本来提高效率和技术运营速度。您如何看待公司将如何实现这一目标? 107.假设一家公司想要修改其部署方法,并希望构建一个可扩展性和响应性更高的平台。您如何看待这家公司能够实现这一目标以满足…...
grafana全家桶-loki promtail收集k8s容器日志
loki是grafana旗下轻量级日志收集工具,为了减少loki对集群的影响,把loki的agent日志收集端promtail部署在k8s集群中,loki server部署在集群外面。这样简单做一个解耦,避免大量读写的应用影响到集群内业务服务。 一、promtail部署…...
HTML5+CSS+JavaScript剪子石头布游戏
HTML5CSSJavaScript剪子石头布游戏 用HTML5CSSJavaScript剪子石头布游戏实现剪子石头布游戏,游戏有成绩计数,人、机输赢情况,及平局情况。 ✂代表剪刀,▉代表石头,▓ 代表布,给出人机双方的出拳情况 游戏…...
Flask-3
文章目录 ORMFlask-SQLAlchemySQLAlchemy中的session对象数据库连接设置常用的SQLAlchemy字段类型常用的SQLAlchemy列约束选项 数据库基本操作模型类定义 数据表操作创建和删除表 数据操作基本查询SQLAlchemy常用的查询过滤器SQLAlchemy常用的查询结果方法多条件查询分页器聚合…...
Redis的基本使用
简介 传统的数据库是 关系数据库,但是Redis是键值对数据库传统的数据库是基于 磁盘存储的,但是Redis是基于 内存存储的 基于内存,读写性能更高内存是不大的,只能存储热点信息 安装 绿色软件,安装即可使用 安装服务 手…...
[241004] Linux 系统中配置文件的区别 | VirtualBox 7.1.2 发布,修复多项问题并提升性能
目录 Linux 系统中 /etc/profile, ~/.bash_profile, ~/.profile, ~/.bashrc 等配置文件的区别一、配置文件类型二、配置文件作用三、交互式登录 Shell 和非登录 Shell交互式登录 shell交互式非登录 shell 四、配置文件加载顺序五、~/.bash_profile 和 ~/.bashrc 的区别 Virtual…...
hbuilderx+uniapp+Android宠物用品商城领养服务系统的设计与实现 微信小程序沙箱支付
目录 项目介绍支持以下技术栈:具体实现截图HBuilderXuniappmysql数据库与主流编程语言java类核心代码部分展示登录的业务流程的顺序是:数据库设计性能分析操作可行性技术可行性系统安全性数据完整性软件测试详细视频演示源码获取方式 项目介绍 顾客 领养…...
SVN 迁移到 GIT,并保留提交记录
1)svn账号与git账号映射 创建 user.txt ,格式如下,user.txt 放置在git base here 所选目录下即可 schacon Scott Chacon <schacongeemail.com> selse Someo Nelse <selsegeemail.com> 为了获得 SVN 使用的作者名字列表…...
【数据结构与算法】LeetCode:堆和快排
文章目录 LeetCode:堆和快排排序数组数组中的第K个最大元素 (Hot 100)前 K 个高频元素(Hot 100)数据流的中位数(Hot 100) LeetCode:堆和快排 排序数组 排序数组 双向切分实现快排…...
浅谈 React Hooks
React Hooks 是 React 16.8 引入的一组 API,用于在函数组件中使用 state 和其他 React 特性(例如生命周期方法、context 等)。Hooks 通过简洁的函数接口,解决了状态与 UI 的高度解耦,通过函数式编程范式实现更灵活 Rea…...
Linux链表操作全解析
Linux C语言链表深度解析与实战技巧 一、链表基础概念与内核链表优势1.1 为什么使用链表?1.2 Linux 内核链表与用户态链表的区别 二、内核链表结构与宏解析常用宏/函数 三、内核链表的优点四、用户态链表示例五、双向循环链表在内核中的实现优势5.1 插入效率5.2 安全…...
python/java环境配置
环境变量放一起 python: 1.首先下载Python Python下载地址:Download Python | Python.org downloads ---windows -- 64 2.安装Python 下面两个,然后自定义,全选 可以把前4个选上 3.环境配置 1)搜高级系统设置 2…...
解决Ubuntu22.04 VMware失败的问题 ubuntu入门之二十八
现象1 打开VMware失败 Ubuntu升级之后打开VMware上报需要安装vmmon和vmnet,点击确认后如下提示 最终上报fail 解决方法 内核升级导致,需要在新内核下重新下载编译安装 查看版本 $ vmware -v VMware Workstation 17.5.1 build-23298084$ lsb_release…...
对WWDC 2025 Keynote 内容的预测
借助我们以往对苹果公司发展路径的深入研究经验,以及大语言模型的分析能力,我们系统梳理了多年来苹果 WWDC 主题演讲的规律。在 WWDC 2025 即将揭幕之际,我们让 ChatGPT 对今年的 Keynote 内容进行了一个初步预测,聊作存档。等到明…...
免费数学几何作图web平台
光锐软件免费数学工具,maths,数学制图,数学作图,几何作图,几何,AR开发,AR教育,增强现实,软件公司,XR,MR,VR,虚拟仿真,虚拟现实,混合现实,教育科技产品,职业模拟培训,高保真VR场景,结构互动课件,元宇宙http://xaglare.c…...
NPOI操作EXCEL文件 ——CAD C# 二次开发
缺点:dll.版本容易加载错误。CAD加载插件时,没有加载所有类库。插件运行过程中用到某个类库,会从CAD的安装目录找,找不到就报错了。 【方案2】让CAD在加载过程中把类库加载到内存 【方案3】是发现缺少了哪个库,就用插件程序加载进…...
[论文阅读]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…...
DAY 26 函数专题1
函数定义与参数知识点回顾:1. 函数的定义2. 变量作用域:局部变量和全局变量3. 函数的参数类型:位置参数、默认参数、不定参数4. 传递参数的手段:关键词参数5 题目1:计算圆的面积 任务: 编写一…...
基于开源AI智能名片链动2 + 1模式S2B2C商城小程序的沉浸式体验营销研究
摘要:在消费市场竞争日益激烈的当下,传统体验营销方式存在诸多局限。本文聚焦开源AI智能名片链动2 1模式S2B2C商城小程序,探讨其在沉浸式体验营销中的应用。通过对比传统品鉴、工厂参观等初级体验方式,分析沉浸式体验的优势与价值…...
