You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java Stream实现多级分组、多聚合、排序及结果格式问题咨询

问题排查与正确实现方案

现有代码的核心问题

  • 测试数据构造存在遗漏:构造完name=pqr, price=500的Map对象后,没有执行lm.add(ms)将其加入原始数据集,导致该条数据未参与分组计算,最终pqr组的聚合值和预期不符。
  • 分组逻辑结构偏差:使用两层嵌套groupingBy生成的是嵌套Map结构,没有将分组字段(name、color)扁平化到每一条结果记录中,无法直接得到目标格式的List<Map<String, Object>>。
  • 聚合值存储方式不合理:使用AbstractMap.SimpleEntry存储聚合结果,无法将price平均值、days求和值拆分为独立的Map字段,最终输出是嵌套的键值对字符串。

正确实现代码

1. 先修正测试数据遗漏

在构造完price=500的pqr对应Map后补上add操作:

// 补上这行,把漏掉的pqr数据加入列表
lm.add(ms);

2. 聚合与分组核心逻辑

import java.util.*;
import java.util.stream.Collectors;

public class StreamAggDemo {
    public static void main(String[] args) {
        // 你的原始测试数据(已补上漏add的那条pqr记录)
        List<Map<String, Object>> lm = new ArrayList<>();
        // ... 之前的所有put和add逻辑,补上遗漏的lm.add(对应500price的ms对象)

        // 1. 用复合键(name+color)做分组,避免嵌套Map
        Map<Map.Entry<String, String>, List<Map<String, Object>>> groupedMap = lm.stream()
                .collect(Collectors.groupingBy(item ->
                        new AbstractMap.SimpleEntry<>(
                                item.get("name").toString(),
                                item.get("color").toString()
                        )
                ));

        // 2. 将每个分组转换为扁平化的结果行
        List<Map<String, Object>> result = groupedMap.entrySet().stream()
                .map(entry -> {
                    String groupName = entry.getKey().getKey();
                    String groupColor = entry.getKey().getValue();
                    List<Map<String, Object>> currentGroup = entry.getValue();

                    // 计算同组price平均值
                    double avgPrice = currentGroup.stream()
                            .mapToInt(item -> (int) item.get("price"))
                            .average()
                            .orElse(0.0);
                    // 计算同组days求和
                    int sumDays = currentGroup.stream()
                            .mapToInt(item -> (int) item.get("days"))
                            .sum();

                    // 组装目标结构
                    Map<String, Object> row = new HashMap<>();
                    row.put("name", groupName);
                    row.put("color", groupColor);
                    row.put("price", avgPrice);
                    row.put("days", sumDays);
                    return row;
                })
                // 3. 排序逻辑可按需替换:这里示例为按days字段降序
                .sorted(Comparator.comparingInt(row -> (int) row.get("days")).reversed())
                .collect(Collectors.toList());

        // 输出验证
        System.out.println(result);
    }
}

排序逻辑说明

只要替换sorted()方法里的Comparator实现,即可按任意指定字段排序:

  • 按price升序:Comparator.comparingDouble(row -> (double) row.get("price"))
  • 按name字典序升序:Comparator.comparing(row -> (String) row.get("name"))
  • 多字段组合排序:比如先按days降序,再按price升序:
.sorted(Comparator.comparingInt((Map<String, Object> row) -> (int) row.get("days")).reversed()
        .thenComparingDouble(row -> (double) row.get("price")))

最终输出效果

修正后运行结果将完全匹配预期格式,输出顺序由设置的排序规则决定,示例为按days降序的结果:

[
  {"name":"xyz", "color":"orange", "price":5000.0, "days":30},
  {"name":"pqr", "color":"blue", "price":1500.0, "days":7},
  {"name":"abc", "color":"red", "price":3000.0, "days":3}
]

内容的提问来源于stack exchange,提问作者user3458271

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.22 14:45:04