如何优雅实现Map<MetricResult, Long>转endTime唯一的List<MetricResult>
问题解决:按endTime去重并保留computationTime最大的MetricResult
问题场景
现有Map<MetricResult, Long>类型集合metricResultToComputationTime,需将其转换为List<MetricResult>,要求:
- 列表中每个
MetricResult的endTime唯一 - 若存在
endTime相同的元素,保留对应Map中value(computationTime)更大的那个
你尝试的代码无法编译,报错信息翻译如下:
找不到合适的
collect方法:
method java.util.stream.Stream.collect(java.util.function.Supplier,java.util.function.BiConsumer<R,? super java.util.Map.Entry<MetricResult,Timestamp>>,java.util.function.BiConsumer<R,R>) 不适用
(推断变量T存在不兼容的边界,上界为MetricResult、java.util.Map.Entry<K,V>、T,T,下界为MetricResult、Timestamp)
错误原因
你的代码中,stream()处理的是Map.Entry<MetricResult, Long>类型元素,但groupingBy的分类器直接使用MetricResult::getEndTime——这个方法引用是针对MetricResult实例的,而当前流中的元素是Map.Entry,编译器无法自动从Entry推断到它的key,导致类型不匹配。
优雅修正方案
方案1:基于groupingBy的修正实现
import static java.util.stream.Collectors.*; import java.util.Objects; import java.util.List; List<MetricResult> metricResults = metricResultToComputationTime.entrySet().stream() .collect(groupingBy( // 明确从Entry的key中提取endTime作为分组键 entry -> entry.getKey().getEndTime(), // 分组内取value最大的Entry,再提取对应的MetricResult collectingAndThen( maxBy(Map.Entry.comparingByValue()), optionalEntry -> optionalEntry.map(Map.Entry::getKey).orElse(null) ) )) .values() .stream() .filter(Objects::nonNull) .collect(toList());
关键修正点:
- 分类器改为
entry -> entry.getKey().getEndTime(),明确从流中的Map.Entry获取MetricResult实例的endTime - 用
optionalEntry.map(Map.Entry::getKey)安全提取目标对象,避免直接get()的空指针风险 - 最后通过
stream().collect(toList())将Collection转为标准List
方案2:更简洁的toMap实现
import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; List<MetricResult> metricResults = new ArrayList<>(metricResultToComputationTime.entrySet().stream() .collect(Collectors.toMap( // 分组键:endTime entry -> entry.getKey().getEndTime(), // 映射值:MetricResult实例 Map.Entry::getKey, // 合并规则:保留computationTime更大的MetricResult (existing, replacement) -> metricResultToComputationTime.get(existing) > metricResultToComputationTime.get(replacement) ? existing : replacement )) .values());
优势:直接通过toMap完成分组、去重、合并逻辑,代码更紧凑,无需嵌套多层收集器。
内容的提问来源于stack exchange,提问作者Akhil Cherian Verghese
相关产品推荐
相关产品推荐

