
使用 java 8 stream 和 collectors.tomap,可高效实现按 name 分组、保留每组 quantity 最大的 item,并返回去重后的结果列表。
使用 java 8 stream 和 collectors.tomap,可高效实现按 name 分组、保留每组 quantity 最大的 item,并返回去重后的结果列表。
在处理具有重复名称但不同数量的 Item 对象列表时,常见需求是:对相同 name 的所有 Item 取 quantity 最大者,最终得到一个无重复 name、且每个 name 对应最大 quantity 的结果列表。这本质上是一个“分组 + 归约(取最大值)”操作,而 Collectors.toMap 正是为此类场景设计的理想工具。
核心思路是将 itemList 流式收集为一个 Map,其中:
- key 为
Item::getName(即名称), - value 为
Item本身(用Function.identity()表示), - 合并函数
(item1, item2) -> item1.getQuantity() >= item2.getQuantity() ? item1 : item2定义当遇到同名 item 时,保留 quantity 更大的那个。
完整代码如下:
List<item> maxItems = itemList.stream()
.collect(Collectors.toMap(
Item::getName, // key: name
Function.identity(), // value: item itself
(item1, item2) -> item1.getQuantity() >= item2.getQuantity()
? item1 : item2 // merge: keep the one with larger quantity
))
.values() // Collection<item> — all "max-per-name" items
.stream()
.collect(Collectors.toList()); // Optional: convert to ArrayList if needed</item></item>
⚠️ 注意事项:
-
toMap返回的是Map,其values()是Collection,若需List类型(如保持插入顺序或兼容旧接口),建议额外调用.stream().collect(Collectors.toList()); - 若原始列表中存在
nullname,会抛出NullPointerException,建议提前过滤或使用Objects.toString(item.getName(), "")做空安全处理; - 该方案时间复杂度为 O(n),优于先求全局最大值再 filter 的方式(后者无法解决“每个 name 的局部最大值”问题);
- 若需按 name 字典序或 quantity 排序输出,可在最后链式调用
.sorted(Comparator.comparing(Item::getName))或.sorted((a, b) -> Integer.compare(b.getQuantity(), a.getQuantity()))。
总结:相比手动遍历或多次 stream 操作,Collectors.toMap 提供了一种简洁、高效、声明式的解决方案,精准契合“分组取极值”这一典型数据聚合需求。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











