Java Comparator 实战:多字段排序、thenComparing、reversed 与 null 值处理
Java Comparator 实战:多字段排序、thenComparing、reversed 与 null 值处理排序是天天写的活,但一到「按多个字段排」就容易翻车。比如一个订单列表,要求先按金额从高到低,金额相同再按下单时间从早到晚,时间还相同按订单号排。很多人写出来的是一坨嵌套 if 的compare方法,读都读不顺,还经常把升序降序搞反。其实 Java 8 之后Comparator提供了一套链式 API,上面这个需求一行就能表达清楚。这篇把comparing、thenComparing、reversed和最容易炸的 null 处理讲透。先看笨办法为什么难维护假设有个订单类:recordOrder(Stringid,intamount,LocalDateTimecreatedAt){}要「金额降序,金额相同按时间升序」,手写compare长这样:orders.sort((a,b)-{intcmpInteger.compare(b.amount(),a.amount());// 注意 b、a 反着写才是降序if(cmp!0)returncmp;returna.createdAt().compareTo(b.createdAt());// 这里又是 a、b 正序});问题很明显:降序要靠「把参数写反」来实现,一眼看不出意图,加字段就得再嵌一层 if,时间一长没人敢动。正确写法:comparing thenComparing链式 API 让排序规则读起来跟需求描述一模一样:importjava.util.Comparator;orders.sort(Comparator.comparingInt(Order::amount).reversed()// 金额降序.thenComparing(Order::createdAt)// 金额相同,时间升序.thenComparing(Order::id)// 再相同,按 id);comparing抽取排序字段,thenComparing追加次级规则(只有前面比出相等才会用到它),reversed把当前顺序反过来。加字段就是再接一个thenComparing,清清爽爽。对基本类型有专门的方法避免装箱:comparingInt、comparingLong、comparingDouble。字段是 int 就用comparingInt,别用泛型版comparing,能省掉 Integer 的自动装箱。坑一:reversed() 到底反转了什么reversed()反转的是它前面整条链,不是某一个字段,这是最常被误解的点。看这两个的区别:// 写法 A:reversed 只作用在 amount 上吗?不是!Comparator.comparingInt(Order::amount).thenComparing(Order::createdAt).reversed();// 实际效果:金额升序→降序,时间也跟着从升序变降序!整条链全反了// 写法 B:只想 amount 降序、时间保持升序,得单独反 amountComparator.comparingInt(Order::amount).reversed()// 先把 amount 反成降序.thenComparing(Order::createdAt);// 再接时间升序记住:reversed()反转的是「到目前为止组合出来的那个 Comparator」。想让某个字段单独降序,就在那个字段的comparing后面立刻.reversed(),再往后接别的规则。如果只是想让某个thenComparing的字段降序,可以给它传第二个参数:Comparator.comparingInt(Order::amount).reversed().thenComparing(Order::createdAt,Comparator.reverseOrder());// 时间也降序坑二:字段是 null 时直接 NPE真实数据里字段为 null 太常见了。如果createdAt可能是 null,上面的代码会在比较时抛NullPointerException,因为默认的比较逻辑会去调 null 的compareTo。Comparator提供了nullsFirst和nullsLast包装器,专门处理这种情况——把 null 统一排到最前或最后:orders.sort(Comparator.comparing(Order::createdAt,Comparator.nullsLast(Comparator.naturalOrder())// null 排最后,非 null 之间自然排序));nullsLast(naturalOrder())的意思是:两个都非 null 就按自然顺序比;有 null 就把它放最后;两个都 null 算相等。想让 null 排最前就换nullsFirst。组合排序里某个字段可能为 null,也一样包一层:Comparator.comparingInt(Order::amount).reversed().thenComparing(Order::createdAt,Comparator.nullsLast(Comparator.naturalOrder()));坑三:用 Comparator 找最值,别先排序要找「金额最高的订单」,别sort完取第一个——那是O(n log n)的浪费。Stream.max/min直接收一个 Comparator,O(n)搞定:OptionalOrderrichestorders.stream().max(Comparator.comparingInt(Order::amount));// TreeMap / PriorityQueue 也能直接吃 Comparator 保持有序PriorityQueueOrderpqnewPriorityQueue(Comparator.comparingInt(Order::amount).reversed()// 大顶堆,金额最高的在队首);同一个 Comparator 既能给sort用,也能给max、PriorityQueue、TreeMap用——写一次到处复用,这也是链式 Comparator 比手写 lambda 更值的地方。小结多字段排序用comparing(...).thenComparing(...),读起来跟需求一致,加字段只需再接一段。基本类型用comparingInt/Long/Double避免装箱。reversed()反转的是它前面整条链,不是单个字段;想让某字段单独降序,就在那个字段后立刻.reversed(),或给thenComparing传reverseOrder()。字段可能为 null 时,用nullsFirst/nullsLast包一层,别让它 NPE。找最值用Stream.max/min收 Comparator,别排完序取第一个;Comparator 还能直接喂给PriorityQueue、TreeMap。一句话记忆:排序规则要「像读句子一样」链式声明出来,而 reversed 反的是「整句」不是「一个词」。

相关新闻

ZXPInstaller终极指南:3分钟搞定Adobe插件安装的免费神器 [特殊字符]

ZXPInstaller终极指南:3分钟搞定Adobe插件安装的免费神器 [特殊字符]

ZXPInstaller终极指南:3分钟搞定Adobe插件安装的免费神器 🚀 【免费下载链接】ZXPInstaller Open Source ZXP Installer for Adobe Extensions 项目地址: https://gitcode.com/gh_mirrors/zx/ZXPInstaller 还在为Adobe插件安装发愁吗?…

2026/8/5 12:04:24 阅读更多 →
OrCAD 17.4深度评测:从交互重构到约束管理,全面解析PCB设计效率革新

OrCAD 17.4深度评测:从交互重构到约束管理,全面解析PCB设计效率革新

1. 项目概述:为什么说OrCAD 17.4是效率的“分水岭”? 如果你是一名电子工程师,或者正在学习PCB设计,那么对Cadence OrCAD这个名字一定不陌生。它几乎是原理图设计和中小规模PCB布局的代名词,以其强大的功能和相对友好的…

2026/8/5 12:04:24 阅读更多 →
扣子多模态消息性能拐点预警:当图文消息加载超时率>3.7%,必须立即执行的6项JVM与CDN协同优化

扣子多模态消息性能拐点预警:当图文消息加载超时率>3.7%,必须立即执行的6项JVM与CDN协同优化

更多请点击: https://intelliparadigm.com 第一章:扣子多模态消息性能拐点预警机制解析 扣子(Dify)平台在处理多模态消息(含文本、图像、音频嵌入及跨模态对齐请求)时,随着并发量与上下文长度增…

2026/8/5 12:04:24 阅读更多 →

最新新闻

Unity异步纹理加载终极方案:UniTask与AsyncGPUReadback实现无缝显示

Unity异步纹理加载终极方案:UniTask与AsyncGPUReadback实现无缝显示

1. 项目概述与核心痛点在Unity项目开发中,尤其是那些包含大量高清贴图、复杂模型或者需要动态加载资源的应用里,纹理加载导致的卡顿和画面撕裂是开发者最头疼的问题之一。你肯定遇到过这样的场景:玩家在开放世界中奔跑,远处的风景…

2026/8/5 15:48:06 阅读更多 →
微信小程序视频封面获取:从API兼容到服务端生成的完整方案

微信小程序视频封面获取:从API兼容到服务端生成的完整方案

1. 项目缘起:一个看似简单却暗藏玄机的需求 最近在做一个社区分享类的小程序,用户需要上传视频。产品经理提了个需求:用户选择视频后,不能只显示一个干巴巴的文件名,得立刻展示一个视频封面图,这样列表看起…

2026/8/5 15:48:06 阅读更多 →
Blender Screencast Keys:5分钟掌握3D创作操作可视化终极指南

Blender Screencast Keys:5分钟掌握3D创作操作可视化终极指南

Blender Screencast Keys:5分钟掌握3D创作操作可视化终极指南 【免费下载链接】Screencast-Keys Blender Add-on: Screencast Keys 项目地址: https://gitcode.com/gh_mirrors/sc/Screencast-Keys Screencast Keys是一款革命性的Blender插件,通过…

2026/8/5 15:48:06 阅读更多 →
Godot引擎卡通渲染实战:从Cel Shading到轮廓线的完整指南

Godot引擎卡通渲染实战:从Cel Shading到轮廓线的完整指南

1. 项目概述:为什么要在Godot里折腾卡通渲染?如果你是一个独立游戏开发者,或者是一个对独特视觉风格有追求的创作者,那么“卡通渲染”这个词对你来说一定不陌生。它不是什么新鲜玩意儿,从《塞尔达传说:风之…

2026/8/5 15:48:06 阅读更多 →
如何快速使用可视化元数据编辑器:新手完整指南

如何快速使用可视化元数据编辑器:新手完整指南

如何快速使用可视化元数据编辑器:新手完整指南 【免费下载链接】ExifToolGui A GUI for ExifTool 项目地址: https://gitcode.com/gh_mirrors/ex/ExifToolGui 想象一下,你刚从旅行回来,手机和相机里存着上千张照片,每张照片…

2026/8/5 15:48:06 阅读更多 →
Lunalytics数据库迁移教程:从SQLite到PostgreSQL无缝切换

Lunalytics数据库迁移教程:从SQLite到PostgreSQL无缝切换

Lunalytics数据库迁移教程:从SQLite到PostgreSQL无缝切换 【免费下载链接】Lunalytics 🚀 Open source monitoring tool built with Node.js 项目地址: https://gitcode.com/gh_mirrors/lu/Lunalytics Lunalytics是一款开源监控工具,使…

2026/8/5 15:47:06 阅读更多 →

日新闻

Java缓存框架:JetCache

Java缓存框架:JetCache

TOC 一、简介 JetCache 是一个 Java 缓存抽象框架,为不同的缓存解决方案提供了统一的使用方式。 它提供的注解比 Spring Cache 更加强大。 JetCache 的注解支持原生 TTL、两级缓存以及在分布式环境中的自动刷新功能,同时你也可以通过代码直接操作 Cach…

2026/8/5 0:00:43 阅读更多 →
AD 铺铜设置十字连接,过孔全连接,新版AD的简单设置

AD 铺铜设置十字连接,过孔全连接,新版AD的简单设置

需求:通孔焊盘 十字花;过孔 Via 实心直连;贴片焊盘按需设置 AD 测试版本AD24 很多工程师踩坑:全部统一十字,导致接地过孔阻抗高、大电流发热! 一、快捷键打开规则 PCB 界面按下:D R 展开…

2026/8/5 0:00:43 阅读更多 →
AI素描转换技术深度拆解(2024最新论文+工业级落地代码):从Stable Diffusion ControlNet到LoRA微调全链路解析

AI素描转换技术深度拆解(2024最新论文+工业级落地代码):从Stable Diffusion ControlNet到LoRA微调全链路解析

更多请点击: https://kaifayun.com 第一章:AI生成素描效果 AI生成素描效果是计算机视觉与风格迁移技术融合的典型应用,其核心在于将彩色照片或RGB图像转换为具有手绘质感、明暗对比强烈、边缘清晰的单色素描图像。该过程通常依赖于深度学习模…

2026/8/5 0:00:43 阅读更多 →

周新闻

最大流算法详解:从水管网络到Ford-Fulkerson与Dinic实战

最大流算法详解:从水管网络到Ford-Fulkerson与Dinic实战

1. 从水管网络到最大流:一个核心问题的诞生想象一下,你是一个城市供水系统的总工程师。你的城市有多个水源(水库),需要通过一个复杂的地下管道网络,将水输送到各个居民区。每条管道都有其最大通水能力&…

2026/8/5 15:00:43 阅读更多 →
基于Springboot的企业门户网站(源码+LW+调试文档+讲解)

基于Springboot的企业门户网站(源码+LW+调试文档+讲解)

温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台…

2026/8/5 13:13:56 阅读更多 →
MATLAB xcorr函数详解:从互相关原理到四大实战应用

MATLAB xcorr函数详解:从互相关原理到四大实战应用

1. 从一次信号“找茬”说起:为什么我们需要互相关几年前,我在处理一组声学传感器数据时遇到了一个棘手的问题。我有两个麦克风记录了一段相同的音频信号,理论上它们接收到的声音波形应该非常相似,只是由于麦克风位置不同&#xff…

2026/8/5 10:20:36 阅读更多 →

月新闻

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南 【免费下载链接】BaiduNetdiskPlugin-macOS For macOS.百度网盘 破解SVIP、下载速度限制~ 项目地址: https://gitcode.com/gh_mirrors/ba/BaiduNetdiskPlugin-macOS 还在为百度网盘macOS版的龟速下…

2026/8/4 13:38:24 阅读更多 →
终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 还在为网易云音乐下载的NCM格式文件无法在其他播放器播放而烦恼吗?ncmdump解密工具帮你轻松解决这个困…

2026/8/4 11:09:16 阅读更多 →
HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

AgentCard 智能体卡片:为英语学习 App 打造桌面级学习助手适用平台:HarmonyOS 7.0 (API 26 Beta)一、引言 HarmonyOS 7.0(API 26 Beta)新增了 AgentCard 智能体卡片能力,这是继 HMAF(鸿蒙智能体框架&#x…

2026/8/4 13:38:40 阅读更多 →