Java使用Comparator比较双关联字段获取符合规则最值条目
问题说明
使用Java Comparator处理列表时,需求为:找到存在有效高分值的最小索引,返回该索引下分值最高的条目。
测试用例
- 用例1
| Index | Score |
|---|---|
| 1 | 100 |
| 1 | 110 |
| 2 | 150 |
预期输出:1 - 110
- 用例2
| Index | Score |
|---|---|
| 1 | null |
| 1 | null |
| 2 | 150 |
| 2 | 110 |
预期输出:2 - 150
原有代码问题
给出的代码运行时会抛出空指针异常,也无法输出正确结果,核心问题有三个:
- 排序优先级错误:原比较器先按索引倒序排列,会优先匹配大索引条目,和「找最小索引」的需求完全相反
- 空值未做兼容:
thenComparing(CompareMe::getScore)默认不支持null值比较,遇到score为null的条目会直接触发空指针 - 实现逻辑不符合需求:需求需要先排除无有效分值的索引、再定位最小索引、最后取该索引下的最高分值,不是直接对全量列表做一次排序取最大值就能实现的。
可运行的正确实现
import java.util.ArrayList; import java.util.Comparator; import java.util.List; import java.util.Optional; public class CompareMe { private int index; private Integer score; public CompareMe(int index, Integer score) { this.index = index; this.score = score; } public int getIndex() { return index; } public Integer getScore() { return score; } public static void main(String[] args) { // 测试用例1 List<CompareMe> list = new ArrayList<>(); list.add(new CompareMe(1, 100)); list.add(new CompareMe(1, 110)); list.add(new CompareMe(2, 150)); getResult(list).ifPresent(e -> System.out.println(e.getIndex() + "-" + e.getScore())); // 测试用例2 list = new ArrayList<>(); list.add(new CompareMe(1, null)); list.add(new CompareMe(1, null)); list.add(new CompareMe(2, 150)); list.add(new CompareMe(2, 110)); getResult(list).ifPresent(e -> System.out.println(e.getIndex() + "-" + e.getScore())); } private static Optional<CompareMe> getResult(List<CompareMe> list) { // 1. 过滤掉score为null的无效条目 // 2. 找到有效条目中的最小索引 // 3. 筛选该最小索引下的所有有效条目,取score最高的 return list.stream() .filter(e -> e.getScore() != null) .min(Comparator.comparingInt(CompareMe::getIndex)) .map(targetIndexItem -> list.stream() .filter(e -> e.getIndex() == targetIndexItem.getIndex() && e.getScore() != null) .max(Comparator.comparingInt(CompareMe::getScore)) .orElseThrow()); } }
实现逻辑说明
- 第一步先过滤所有score为null的条目,既避免后续空指针,也直接排除了没有有效分值的索引
- 从有效条目中取索引最小的条目,拿到需要匹配的目标索引
- 二次筛选出所有属于目标索引的有效条目,取score最高的即为最终结果
- 用Optional封装返回值,兼容列表全为null score的极端边界场景,避免运行时异常
内容的提问来源于stack exchange,提问作者Neo
相关产品推荐
相关产品推荐

