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

如何用函数式风格通过Apache Common CSV按月分组并对数据求和

Java Stream 按周/月分组求和实现方案

核心思路

  • 避免将解析后的日期转回字符串格式,直接使用LocalDate对象内置的时间属性做分组依据,简化后续逻辑
  • 利用Stream自带的Collectors.groupingBy做分组,配合summingInt/reducing聚合器直接完成求和操作,全程符合函数式编程规范

优化实现代码

1. 定义业务数据实体(可选但更易维护)

如果是Java 16及以上版本可以直接用record,低版本替换为普通POJO即可:

// 按你的数据集字段调整,这里假设包含日期和待求和的数值两个核心字段
public record DataRow(LocalDate date, BigDecimal amount) {}

2. 优化CSV解析逻辑

直接将CSV行映射为业务实体,避免二次处理:

public List<DataRow> csvParser(String CSVFileName) throws IOException {
    DateTimeFormatter rawDateFormatter = DateTimeFormatter.ofPattern("M/d/yy");
    // 用try-with-resources自动关闭资源
    try(CSVParser csvParser = CSVParser.parse(Paths.get(CSVFileName), Charset.defaultCharset(), CSVFormat.DEFAULT)) {
        return csvParser
                .stream()
                // 按你实际的CSV列索引调整get的参数值
                .map(record -> new DataRow(
                        LocalDate.parse(record.get(0), rawDateFormatter),
                        new BigDecimal(record.get(1))
                ))
                .collect(Collectors.toList());
    }
}

3. 按月分组求和实现

public Map<String, BigDecimal> calculateSumByMonth(List<DataRow> dataRows) {
    DateTimeFormatter monthFormatter = DateTimeFormatter.ofPattern("yyyy-MM");
    return dataRows.stream()
            .collect(Collectors.groupingBy(
                    row -> row.date().format(monthFormatter),
                    // 数值为整数的话可以替换为 Collectors.summingInt(DataRow::amount)
                    Collectors.reducing(BigDecimal.ZERO, DataRow::amount, BigDecimal::add)
            ));
}

4. 按周分组求和实现

默认用ISO标准周(周一为一周起始),如果需要周日为起始可以调整WeekFields配置:

public Map<String, BigDecimal> calculateSumByWeek(List<DataRow> dataRows) {
    // ISO周格式:年份-周数,自动处理跨年周问题
    DateTimeFormatter weekFormatter = DateTimeFormatter.ofPattern("YYYY-ww");
    // 若要求周日为一周起始,用下方自定义逻辑替换formatter即可
    // WeekFields weekFields = WeekFields.of(DayOfWeek.SUNDAY, 1);
    // Function<LocalDate, String> weekKeyGenerator = date -> date.getYear() + "-" + date.get(weekFields.weekOfWeekBasedYear());
    return dataRows.stream()
            .collect(Collectors.groupingBy(
                    row -> row.date().format(weekFormatter),
                    Collectors.reducing(BigDecimal.ZERO, DataRow::amount, BigDecimal::add)
            ));
}

注意事项

  • 代码全程无可变中间变量,所有操作都是无副作用的函数式实现,符合作业要求
  • 可根据你的数据集实际字段数量、求和字段类型灵活调整聚合逻辑,比如多字段求和可以用teeing聚合器组合多个求和规则

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 22:36:06