2026年3月,JDK 26 正式发布。虽然大版本的功能迭代节奏有所放缓,但一些精心打磨的“小而美”改进,往往更能击中开发者的日常痛点。本次更新中,java.util.Comparator 接口迎来了一个实用性极强的增强:新增了 min(T, T) 和 max(T, T) 两个默认方法。这个由 JetBrains 工程师 Tagir Valeev 贡献的特性,旨在解决一个看似简单却困扰了 Java 程序员许久的问题:如何优雅地比较两个对象并直接获取较大或较小的那个。
为什么需要这两个方法?
在日常编程中,我们经常遇到这样的场景:给定两个对象和一个比较器(Comparator),需要找出其中较大或较小的一个。在 JDK 26 之前,我们主要有以下几种实现方式,但各有各的不足。
方案一:三元运算符
这是最直接、也最常用的方法,但写起来总感觉不够优雅。
String max = comp.compare(a, b) > 0 ? a : b;
这类代码的痛点很明显:需要重复书写变量名 a 和 b,并且必须仔细匹配 > 或 < 符号与三元运算符返回值的对应关系。代码可读性一般,稍不注意就容易弄错 compare 方法返回值的含义,导致逻辑错误。
方案二:Stream API
这个方案语义清晰,但有种“杀鸡用牛刀”的感觉,属于过度设计。
String max = Stream.of(a, b).max(comp).get();
虽然意图明确,但为了比较两个元素,我们创建了一个 Stream 和一个 Optional 对象(明明知道流中至少有两个元素,结果必然存在)。这不仅可能带来不必要的性能开销和堆内存分配,其简洁性也打了折扣。
方案三:BinaryOperator
这个方案功能上没问题,但写起来略显冗长且不够直观。
String max = BinaryOperator.maxBy(comp).apply(a, b);
它是现有方案中字符数最多的。虽然逻辑相对清晰,但 maxBy(comp).apply(a, b) 的链式调用远不如我们心中理想的 comp.max(a, b) 来得直观。此外,它也会创建不必要的函数对象。如果比较器定义在更抽象的类型上,还需要显式指定类型参数,更添繁琐。
Comparator<CharSequence> comp = Comparator.comparingInt(CharSequence::length);
// 这里 <String> 类型参数是必需的
String max = BinaryOperator.<String>maxBy(comp).apply("long", "short");
正是这些“能跑,但不够美”的方案,催生了社区的改进提案。

JDK 26 的解决方案
JDK 26 为 Comparator 接口新增了两个默认方法,让一切变得简单。
public interface Comparator<T> {
// ... 其他方法
default <U extends T> U max(U o1, U o2) {
return compare(o1, o2) > 0 ? o1 : o2;
}
default <U extends T> U min(U o1, U o2) {
return compare(o1, o2) > 0 ? o2 : o1;
}
}
现在,代码可以写得异常简洁和直观,就像使用 Math.max() 一样自然。
Comparator<String> byLength = Comparator.comparingInt(String::length);
// 直接调用比较器的方法
System.out.println(byLength.max("cat", "giraffe")); // 输出: giraffe
System.out.println(byLength.min("cat", "giraffe")); // 输出: cat
// 甚至可以这样用
String bigger = String.CASE_INSENSITIVE_ORDER.max("Hello", "world");
这种设计完美融入了 Java 标准库的风格,极大地提升了代码的可读性和编写效率。如果你正在深入学习 Java 的核心 API,这个改进是一个很好的观察点。

主要使用场景
这两个新方法特别适合以下场景:
- 两值比较:当只需要比较两个对象时,无需再创建集合或流。
- 链式比较:在复杂的比较逻辑中,快速选取多个候选值中的极值。
- 配置选择:根据某些条件,在两个配置对象中选择更优的一个。
- 边界处理:在算法实现中,那些频繁需要取较大/较小值的场景。
特性演进历程:社区协作的力量
这个“小而美”的特性从提案到落地,完整展现了 OpenJDK 社区的协作流程。
- 提案提出 (2025年5月):Tagir Valeev 在 core-libs-dev 邮件列表中发起讨论,指出了现有方案的不足,并提出了添加
min/max 默认方法的初步想法。
- 社区讨论 (2025年5月-9月):提案在社区中进行了充分讨论。开发者们就方法签名、泛型设计(最终采用了
<U extends T> 以提供灵活性)以及与其他 API 的兼容性进行了深入探讨。
- 代码审查 (2025年9月):经过多轮代码审查(RFR),最终敲定了实现细节。
- 正式发布 (2026年3月):该特性随 JDK 26 正式与开发者见面。

值得一提的是,类似的增强想法早在多年前就有过提案(JDK-4254492),但当时 Java 尚未引入默认方法(Default Methods)这一机制而不得不搁置。直到 Java 8 带来了默认方法,才为这类“向后兼容的接口增强”铺平了道路。
对开发生态的影响
这个改动虽小,却对 Java 开发生态产生了积极的涟漪效应。
- IDE 支持:像 IntelliJ IDEA 这类 IDE 已经开始提供代码检查,建议开发者使用新的
comparator.max()/min() 方法来替代手动的三元运算符等旧方案。
- 代码简化:大量现存项目中的冗长比较代码可以得到简化,提升可维护性。
- 性能提升:直接的方法调用避免了之前使用 Stream API 方案可能产生的额外开销。
当然,变更也带来了一些兼容性考量。例如,Scala 2.13.x 中的 Ordering 特质继承了 Comparator,新增的默认方法会与其已有的 min/max 方法产生冲突,需要显式覆盖来解决。这也是任何 JVM 语言在适配 JDK 新特性时可能遇到的情况。
总结
JDK 26 中为 Comparator 新增的 min(T, T) 和 max(T, T) 方法,是一个典型的实用主义改进。它没有引入复杂的新概念,而是精准地解决了开发者日常编码中的一处不便。从社区提案到最终发布,整个过程体现了 OpenJDK 开放、协作的演进模式。
对于开发者而言,升级到 JDK 26 后,在需要比较两个对象的场景中,代码可以写得更加简洁、意图更加清晰。这也提醒我们,优秀的 Java 生态进化,不仅依赖于轰轰烈烈的大特性,也离不开这些细致入微的打磨。对这类技术演进细节的讨论,也欢迎你在 云栈社区 与其他开发者一起交流。
参考链接
- JDK Bug Tracker:
https://bugs.openjdk.org/browse/JDK-8356995
- OpenJDK Release Notes:
https://jdk.java.net/26/release-notes
- core-libs-dev 讨论:
https://mail.openjdk.org/pipermail/core-libs-dev/2025-May/145638.html