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

Java实现:按日期和会话类型聚合消费与成本数据

实现方案

前提准备

先确认SessionDetail类的基础结构(需包含消费总和与成本总和的字段及构造/访问方法),示例如下:

class SessionDetail {
    private double totalConsumed;
    private double totalCost;

    public SessionDetail(double totalConsumed, double totalCost) {
        this.totalConsumed = totalConsumed;
        this.totalCost = totalCost;
    }

    // 可选:根据业务需求添加getter方法
    public double getTotalConsumed() { return totalConsumed; }
    public double getTotalCost() { return totalCost; }
}

方案1:直接从原始List<Result>生成目标嵌套Map

无需先生成dailyResults,通过Stream一步完成双层分组+求和:

Map<String, Map<String, SessionDetail>> targetMap = results.stream()
        .collect(Collectors.groupingBy(
                Result::getSessionDate, // 外层按sessionDate分组
                Collectors.groupingBy(
                        // 内层按SESSION_TYPE的字符串形式作为键
                        res -> res.getSESSION_TYPE().name(),
                        // 将同类型的Result聚合为SessionDetail
                        Collectors.reducing(
                                new SessionDetail(0.0, 0.0), // 初始累加值
                                // 将单个Result转换为SessionDetail
                                res -> new SessionDetail(res.getConsumed(), res.getCost()),
                                // 累加逻辑:合并两个SessionDetail的数值
                                (detail1, detail2) -> new SessionDetail(
                                        detail1.getTotalConsumed() + detail2.getTotalConsumed(),
                                        detail1.getTotalCost() + detail2.getTotalCost()
                                )
                        )
                )
        ));

优势:仅遍历原始数据集一次,性能更优,代码紧凑。


方案2:基于已有的dailyResults生成目标嵌套Map

如果已经提前得到了按日期分组的dailyResults,可以基于它做二次处理:

方式A:循环遍历处理

Map<String, Map<String, SessionDetail>> targetMap = new HashMap<>();
for (Map.Entry<String, List<Result>> dailyEntry : dailyResults.entrySet()) {
    String date = dailyEntry.getKey();
    List<Result> dailyList = dailyEntry.getValue();

    // 处理单日数据:按SESSION_TYPE分组求和
    Map<String, SessionDetail> typeDetailMap = dailyList.stream()
            .collect(Collectors.groupingBy(
                    res -> res.getSESSION_TYPE().name(),
                    Collectors.collectingAndThen(
                            Collectors.toList(),
                            list -> {
                                // 一次性计算两个字段的总和
                                double sumConsumed = list.stream().mapToDouble(Result::getConsumed).sum();
                                double sumCost = list.stream().mapToDouble(Result::getCost).sum();
                                return new SessionDetail(sumConsumed, sumCost);
                            }
                    )
            ));

    targetMap.put(date, typeDetailMap);
}

方式B:流式处理dailyResults

Map<String, Map<String, SessionDetail>> targetMap = dailyResults.entrySet().stream()
        .collect(Collectors.toMap(
                Map.Entry::getKey,
                entry -> entry.getValue().stream()
                        .collect(Collectors.groupingBy(
                                res -> res.getSESSION_TYPE().name(),
                                Collectors.reducing(
                                        new SessionDetail(0.0, 0.0),
                                        res -> new SessionDetail(res.getConsumed(), res.getCost()),
                                        (d1, d2) -> new SessionDetail(d1.getTotalConsumed() + d2.getTotalConsumed(), d1.getTotalCost() + d2.getTotalCost())
                                )
                        ))
        ));

关键说明

  1. 内层分组键使用SESSION_TYPE.name()将枚举转换为字符串,符合目标Map的String类型键要求;
  2. 若追求性能,优先使用Collectors.reducing(仅遍历分组内数据一次),而非先转List再两次求和;
  3. 若SessionDetail提供了merge方法,可简化累加逻辑,例如:
    // 在SessionDetail中添加merge方法
    public void merge(SessionDetail other) {
        this.totalConsumed += other.getTotalConsumed();
        this.totalCost += other.getTotalCost();
    }
    
    // 此时reducing的累加逻辑可改为
    (detail1, detail2) -> {
        detail1.merge(detail2);
        return detail1;
    }
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 15:30:43