Java Stream 多字段分组(List<对象>)

时间:2025-03-20 10:48:53
public class Test { public static void main(String[] args) { //这里模拟数据 List<Order> orders = Arrays.asList( new Order("安徽","内部订单",100,0), new Order("安徽","内部订单",200,50), new Order("安徽","外部订单",100,100), new Order("河南","内部订单",100,0), new Order("河南","外部订单",300,0), new Order("河南","内部订单",200,100), new Order("河北","内部订单",100,0), new Order("河北","内部订单",100,0), new Order("河北","内部订单",100,0), new Order("江西","内部订单",100,50), new Order("江西","外部订单",100,100)); //先输出一下原始数据 System.out.println("分组之前的数据"); orders.forEach(System.out :: println); System.out.println("分组之后的数据"); //准备好数据之后,调用一下方法 List<Order> ordersByGroup = groupByAddressAndType(orders); //输出一下分组之后的数据 ordersByGroup.forEach(System.out :: println); } /** * 需求: * 按照地址,和订单类型 分组数据 并且 收款金额,和退款金额都要统计 */ public static List<Order> groupByAddressAndType(List<Order> orders) { //这个map 是用来统计收款金额的 Map<String, IntSummaryStatistics> priceMap = orders.parallelStream() .collect(Collectors.groupingBy( //这里按照getAddress 地址 getType 类型来作为分组的条件 最后想要统计的是交易金额 a -> a.getAddress() + "_" + a.getType(), Collectors.summarizingInt(a -> a.getPrice())) ); //这个map 是用来统计退款金额的 Map<String, IntSummaryStatistics> refundMap = orders.parallelStream() .collect(Collectors.groupingBy( //这里按照getAddress 地址 getType 类型来作为分组的条件 最后想要统计的是交易金额 a -> a.getAddress() + "_" + a.getType(), Collectors.summarizingInt(a -> a.getRefund())) ); orders.forEach(order -> { //这个获取map对应值 long price = priceMap.get(order.getAddress() + "_" + order.getType()).getSum(); long refund = refundMap.get(order.getAddress() + "_" + order.getType()).getSum(); //这里把取出来的值 赋给order order.setPrice((int) price); order.setRefund((int) refund); }); //最后返回 return orders.stream().distinct().collect(Collectors.collectingAndThen(Collectors.toCollection( () -> new TreeSet<>( // 这里的规则和 上面分组的规则一样 Comparator.comparing(u -> u.getAddress() + "_" + u.getType()) )), ArrayList::new)); } }