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

如何用Java Lambda与Stream将嵌套Map的周数据转换为月数据

用Java Stream优化嵌套Map的周度转月度指标聚合

核心思路

外层按国家分组,内层将每个国家的周数据按月份归类,再对数值型指标(customerViews、productSales等)做求和聚合,自动跳过缺失的周或缺失的指标。

实现代码

首先实现周标识转月份的工具方法(假设周格式为yyyy-Www,如2024-W01):

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;

private static String getMonthFromWeek(String weekStr) {
    String[] parts = weekStr.split("-W");
    int year = Integer.parseInt(parts[0]);
    int week = Integer.parseInt(parts[1]);
    // 计算该周对应的月份,格式为yyyy-MM
    return LocalDate.ofYearDay(year, week * 7)
            .format(DateTimeFormatter.ofPattern("yyyy-MM"));
}

然后用Stream完成聚合逻辑:

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

// 原始输入数据:Map<String, Map<String, Object>> countryWeeklyData
Map<String, Map<String, Object>> countryMonthlyData = countryWeeklyData.entrySet().stream()
        .collect(Collectors.toMap(
                Map.Entry::getKey, // 保留国家作为外层Map的Key
                countryEntry -> countryEntry.getValue().entrySet().stream()
                        // 过滤掉非指标Map的脏数据
                        .filter(weekEntry -> weekEntry.getValue() instanceof Map)
                        // 按月份分组周数据
                        .collect(Collectors.groupingBy(
                                weekEntry -> getMonthFromWeek(weekEntry.getKey()),
                                // 对同月份的所有周指标求和
                                Collectors.collectingAndThen(
                                        Collectors.toList(),
                                        weekEntries -> {
                                            Map<String, Object> monthlyMetrics = new HashMap<>();
                                            // 定义需要聚合的数值型指标列表
                                            List<String> targetMetrics = Arrays.asList(
                                                    "customerViews", "productSales", "noOfUnitsSold", "conversion"
                                            );

                                            targetMetrics.forEach(metric -> {
                                                double total = weekEntries.stream()
                                                        .map(weekEntry -> (Map<String, Object>) weekEntry.getValue())
                                                        // 跳过缺失当前指标的周数据
                                                        .filter(metricMap -> metricMap.containsKey(metric))
                                                        .mapToDouble(metricMap -> ((Number) metricMap.get(metric)).doubleValue())
                                                        .sum();
                                                monthlyMetrics.put(metric, total);
                                            });
                                            return monthlyMetrics;
                                        }
                                )
                        ))
        ));

关键细节说明

  • 周转月逻辑:如果你的周标识格式不是yyyy-Www,直接修改getMonthFromWeek方法的解析规则即可(比如yyyyMMww格式可以用字符串截取+日期解析)。
  • 缺失值处理:通过filter跳过没有目标指标的周数据,避免空指针;缺失的周数据会自动被忽略,不影响同月份其他周的求和。
  • 类型适配:如果指标是整数类型(如customerViews),求和后可以将double total转为long total再存入Map,贴合数据类型需求。
  • 空数据过滤:如果需要排除没有任何周数据的国家,可在外层Stream添加.filter(entry -> !entry.getValue().isEmpty())。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 11:07:56