Java Stream按关联Product属性分组并统计quantity总和的实现咨询
前置要求
请确保你的三个实体类已实现对应属性的getter方法:
Product类实现getProductName()、getMeasurementUnit()InwardOutwardList类实现getProduct()、getQuantity()InwardInventory类实现getInwardOutwardList()
方案1:使用SimpleEntry作为分组键(兼容所有JDK8+版本)
import java.util.AbstractMap; import java.util.List; import java.util.Map; import java.util.stream.Collectors; // 此处替换为你实际的InwardInventory实例集合变量 List<InwardInventory> inwardInventoryList = ...; Map<AbstractMap.SimpleEntry<String, String>, Double> quantitySumResult = inwardInventoryList.stream() // 打平所有InwardInventory下的出入库明细,得到所有InwardOutwardList实例流 .flatMap(inwardInventory -> inwardInventory.getInwardOutwardList().stream()) // 可选过滤:过滤掉product为空的异常数据,业务可保证非空时可删除 .filter(entry -> entry.getProduct() != null) // 按(产品名、计量单位)分组,求和对应quantity .collect(Collectors.groupingBy( entry -> new AbstractMap.SimpleEntry<>( entry.getProduct().getProductName(), entry.getProduct().getMeasurementUnit() ), // quantity为null时按0计算,业务可保证非空时可简化为Collectors.summingDouble(InwardOutwardList::getQuantity) Collectors.summingDouble(entry -> entry.getQuantity() == null ? 0d : entry.getQuantity()) )); // 遍历结果示例 quantitySumResult.forEach((groupKey, sum) -> { String productName = groupKey.getKey(); String measurementUnit = groupKey.getValue(); System.out.printf("产品名:%s,计量单位:%s,总数量:%.2f%n", productName, measurementUnit, sum); });
方案2:使用Record作为分组键(JDK16+推荐,可读性更高)
import java.util.List; import java.util.Map; import java.util.stream.Collectors; // 定义分组键的记录类,也可单独声明为公共类 record ProductGroup(String productName, String measurementUnit) {} // 统计逻辑 List<InwardInventory> inwardInventoryList = ...; Map<ProductGroup, Double> quantitySumResult = inwardInventoryList.stream() .flatMap(inwardInventory -> inwardInventory.getInwardOutwardList().stream()) .filter(entry -> entry.getProduct() != null) .collect(Collectors.groupingBy( entry -> new ProductGroup( entry.getProduct().getProductName(), entry.getProduct().getMeasurementUnit() ), Collectors.summingDouble(entry -> entry.getQuantity() == null ? 0d : entry.getQuantity()) ));
注意事项
- 如果JDK版本低于16且不想用SimpleEntry,可自定义普通类作为分组键,重写
equals()和hashCode()方法即可。 - 如果需要保留更高精度,可将
summingDouble替换为Collectors.reducing(BigDecimal.ZERO, entry -> BigDecimal.valueOf(entry.getQuantity() == null ? 0d : entry.getQuantity()), BigDecimal::add),同时将Map的value类型改为BigDecimal。
内容的提问来源于stack exchange,提问作者Sridhar Patnaik
相关产品推荐
相关产品推荐

