Java中值为List的Map如何按总得分、非活跃人数规则查找目标Group
解法1:基于你现有代码实现(无需新增if判断)
你已经完成了各分组的总得分、非活跃人数统计,直接用JDK自带的Comparator构造多维度比较规则,配合Stream的max()方法即可实现需求,全程无需手写if判断:
Optional<Group> bestGroupOptional = collect.keySet().stream() // 第一优先级:按总得分升序排列,max()取得分最高的分组 .max(Comparator.comparingInt((Group g) -> collect1.get(g)) // 第二优先级:得分相同时按非活跃人数升序排列,max()取非活跃人数更多的分组 .thenComparingLong(g -> collect2.get(g))); // 按需处理结果,例如无分组时返回默认值 Group bestGroup = bestGroupOptional.orElse(null);
解法2:优化方案(无需单独遍历生成两个统计Map)
你可以直接在分组阶段就完成统计数据的封装,减少中间Map的维护,代码更简洁:
第一步:定义分组统计实体
Java 16+ 可以直接用record定义不可变统计对象:
record GroupStats(int totalScore, long inactiveCount) {}
低版本Java可以自定义普通类实现,补充get方法即可。
第二步:分组同时完成统计
Java 12+ 可以使用Collectors.teeing合并两个收集结果:
Map<Group, GroupStats> groupStatsMap = people.stream() .collect(Collectors.groupingBy( Person::getTeam, Collectors.teeing( // 统计分组总得分 Collectors.summingInt(Person::getScore), // 统计分组非活跃人数 Collectors.filtering(p -> !p.isActive(), Collectors.counting()), GroupStats::new ) ));
低版本Java可以用如下方式实现:
Map<Group, GroupStats> groupStatsMap = people.stream() .collect(Collectors.groupingBy(Person::getTeam)) .entrySet().stream() .collect(Collectors.toMap( Map.Entry::getKey, entry -> { int totalScore = entry.getValue().stream().mapToInt(Person::getScore).sum(); long inactiveCount = entry.getValue().stream().filter(p -> !p.isActive()).count(); return new GroupStats(totalScore, inactiveCount); } ));
第三步:多维度比较获取目标分组
Optional<Group> bestGroupOptional = groupStatsMap.entrySet().stream() .max(Comparator.comparingInt((Map.Entry<Group, GroupStats> entry) -> entry.getValue().totalScore()) .thenComparingLong(entry -> entry.getValue().inactiveCount())) .map(Map.Entry::getKey); Group bestGroup = bestGroupOptional.orElse(null);
逻辑说明
以上两种实现都完全符合需求规则:
- 优先取总得分最高的分组
- 总得分相同时,自动取非活跃人数更多的分组
- 两个维度都相同时,会返回遍历过程中先匹配到的分组,满足「任意返回」的要求
全程没有手动编写if分支判断,完全复用JDK原生比较器能力实现。
内容的提问来源于stack exchange,提问作者Andylg
相关产品推荐
相关产品推荐

