Java 8实现Data列表转带累计求和的DataHistory列表并入库
用Java 8实现Data到DataHistory的累计转换
没问题,这就给你一步步拆解怎么实现这个需求——从包含多日多条记录的Data列表,生成带截至当日累计和的DataHistory列表,还能直接存入数据库用于表格展示。
思路梳理
核心步骤其实很清晰:
- 先把原始
Data按日期分组,计算出每天的int1和int2的当日总和 - 对分组后的日期按时间顺序排序
- 遍历排序后的日期,逐步累加计算截至当日的累计和,最终生成
DataHistory对象
代码实现
首先,我们先调整一下类的定义(推荐用Java 8的LocalDate代替旧的Date类,更安全易用):
import java.time.LocalDate; // 原始数据类 class Data { private LocalDate date; private int int1; private int int2; // 构造器、getter、setter省略,按需实现 public Data(LocalDate date, int int1, int int2) { this.date = date; this.int1 = int1; this.int2 = int2; } public LocalDate getDate() { return date; } public int getInt1() { return int1; } public int getInt2() { return int2; } } // 历史累计数据类 class DataHistory { private LocalDate date; private int sumInt1BeforeOrEqualDate; private int sumInt2BeforeOrEqualDate; private String someOtherValues; // 构造器、getter、setter省略 public DataHistory(LocalDate date, int sumInt1, int sumInt2, String someOtherValues) { this.date = date; this.sumInt1BeforeOrEqualDate = sumInt1; this.sumInt2BeforeOrEqualDate = sumInt2; this.someOtherValues = someOtherValues; } // toString方法方便调试 @Override public String toString() { return "DataHistory{" + "date=" + date + ", sumInt1=" + sumInt1BeforeOrEqualDate + ", sumInt2=" + sumInt2BeforeOrEqualDate + '}'; } }
接下来是核心的转换逻辑,我们用Java 8的Stream API来实现:
import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.Comparator; import java.util.List; import java.util.Map; import java.util.stream.Collectors; public class DataConverter { // 定义日期格式化器,匹配输入的dd/MM/yy格式 private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("dd/MM/yy"); public static void main(String[] args) { // 模拟输入的原始Data列表 List<Data> rawData = List.of( new Data(LocalDate.parse("01/01/18", DATE_FORMATTER), 2, 3), new Data(LocalDate.parse("01/01/18", DATE_FORMATTER), 0, 1), new Data(LocalDate.parse("02/01/18", DATE_FORMATTER), 0, 1), new Data(LocalDate.parse("02/01/18", DATE_FORMATTER), 3, 0), new Data(LocalDate.parse("03/01/18", DATE_FORMATTER), 1, 3) ); // 1. 按日期分组,计算每日的int1和int2总和 Map<LocalDate, DailySum> dailySumMap = rawData.stream() .collect(Collectors.groupingBy( Data::getDate, Collectors.collectingAndThen( Collectors.toList(), list -> new DailySum( list.stream().mapToInt(Data::getInt1).sum(), list.stream().mapToInt(Data::getInt2).sum() ) ) )); // 2. 将分组后的日期按升序排序 List<Map.Entry<LocalDate, DailySum>> sortedDailyEntries = new ArrayList<>(dailySumMap.entrySet()); sortedDailyEntries.sort(Comparator.comparing(Map.Entry::getKey)); // 3. 计算累计和并生成DataHistory列表 List<DataHistory> dataHistoryList = new ArrayList<>(); int cumulativeInt1 = 0; int cumulativeInt2 = 0; for (Map.Entry<LocalDate, DailySum> entry : sortedDailyEntries) { LocalDate date = entry.getKey(); DailySum dailySum = entry.getValue(); cumulativeInt1 += dailySum.getInt1Sum(); cumulativeInt2 += dailySum.getInt2Sum(); // 这里的someOtherValues可以根据业务需求填充,比如固定值或其他计算结果 dataHistoryList.add(new DataHistory(date, cumulativeInt1, cumulativeInt2, "自定义内容")); } // 打印结果验证 dataHistoryList.forEach(System.out::println); } // 临时辅助类,存储每日的int1和int2总和 private static class DailySum { private int int1Sum; private int int2Sum; public DailySum(int int1Sum, int int2Sum) { this.int1Sum = int1Sum; this.int2Sum = int2Sum; } public int getInt1Sum() { return int1Sum; } public int getInt2Sum() { return int2Sum; } } }
代码解释
- 日期分组与每日求和:用
Collectors.groupingBy按日期分组,再通过collectingAndThen把每组的Data列表转换成每日的总和对象DailySum,避免重复计算。 - 日期排序:把Map的entry转成列表后按日期升序排序,保证累计的顺序正确。
- 累计计算:用两个累加变量遍历排序后的每日数据,逐步累加得到截至当日的累计和,最后生成
DataHistory对象。 - 日期解析:用
DateTimeFormatter处理输入的dd/MM/yy格式字符串,转换成LocalDate对象。
运行结果
执行上述代码后,会输出:
DataHistory{date=2018-01-01, sumInt1=2, sumInt2=4} DataHistory{date=2018-01-02, sumInt1=5, sumInt2=5} DataHistory{date=2018-01-03, sumInt1=6, sumInt2=8}
完全符合需求:截至01/01的累计是2和4(2+0,3+1),截至02/01是5(2+3)和5(4+1),截至03/01是6(5+1)和8(5+3)。
如果需要兼容旧的Date类,只需要把LocalDate替换成Date,并调整日期解析的逻辑(比如用SimpleDateFormat)即可。
内容的提问来源于stack exchange,提问作者testeurFou
相关产品推荐
相关产品推荐

