Java如何按多字段分组取最小orderId并对number字段求和
Java Stream 实现多字段分组聚合最优方案
核心实现思路
- 以三个分组字段组成的List作为分组key(List天然支持按元素内容计算hashCode和判等,无需额外自定义分组key类)
- 分组下游直接对同组数据做聚合:提取最小orderId、累加number值,直接构造目标Item对象
- 最终提取分组Map的value转为List即可,全程仅一次分组+一次聚合转换,无多余中间操作
代码实现(兼容Java 8及以上所有版本)
import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; // 核心聚合逻辑 List<Item> result = items.stream() .collect(Collectors.groupingBy( // 按itemId、itemName、itemGenre三个字段分组 item -> Arrays.asList(item.getItemId(), item.getItemName(), item.getItemGenre()), // 同组数据聚合为单个Item对象 Collectors.collectingAndThen(Collectors.toList(), groupItems -> { // 取组内最小的orderId String minOrderId = groupItems.stream() .map(Item::getOrderId) .min(String::compareTo) .orElseThrow(); // 分组非空可直接用异常兜底 // 聚合number求和 int sumNumber = groupItems.stream() .mapToInt(Item::getNumber) .sum(); // 分组字段同组所有元素一致,取首个元素的对应字段即可 Item firstItem = groupItems.get(0); return new Item(minOrderId, firstItem.getItemId(), firstItem.getItemName(), firstItem.getItemGenre(), sumNumber); }) )) .values() .stream() .collect(Collectors.toList()); // 打印输出结果 System.out.println(result);
输出结果
[Item(orderId=00-82-947, itemId=8810, itemName=item name1, itemGenre=01, number=3), Item(orderId=00-91-135, itemId=8315, itemName=item name2, itemGenre=02, number=3), Item(orderId=00-91-140, itemId=8315, itemName=item name3, itemGenre=02, number=4)]
方案优势
- 无需额外创建新的DTO类承载中间结果,直接复用原有Item实体类
- 仅需一次分组操作,无需多次Map转换,代码逻辑直观易维护
- 完全满足需求规则:按指定字段分组、取组内最小orderId、对number求和,最终返回List
- 类型结果
内容的提问来源于stack exchange,提问作者jimi1206
相关产品推荐
相关产品推荐

