如何为生成的日期区间填充缺失月份的对应金额值(Java)
解决方案
现有代码的问题
- 错误使用
List<LocalDate>作为Map的Key,每次循环都会覆盖之前的条目,最终Map仅保留最后一条记录的金额,完全无法实现日期与金额的对应。 - 生成的
totalMonths未包含原始起始日期,且没有针对相邻原始记录的区间填充逻辑,无法覆盖所有需要补全的月份。
正确实现代码
import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; import java.math.BigDecimal; import java.time.LocalDate; import java.util.ArrayList; import java.util.Comparator; import java.util.List; import java.util.stream.Collectors; @Data @Builder @AllArgsConstructor @NoArgsConstructor public class ChildReports { private LocalDate date; private BigDecimal amount; } // 服务类中的补全方法 public List<ChildReports> fillMissingMonths(List<ChildReports> childReports) { // 1. 按日期排序原始数据,确保顺序正确 List<ChildReports> sortedReports = childReports.stream() .sorted(Comparator.comparing(ChildReports::getDate)) .collect(Collectors.toList()); List<ChildReports> filledReports = new ArrayList<>(); if (sortedReports.isEmpty()) { return filledReports; } // 添加第一条原始记录作为起始 filledReports.add(sortedReports.get(0)); // 遍历相邻记录,填充中间月份数据 for (int i = 1; i < sortedReports.size(); i++) { ChildReports prevReport = sortedReports.get(i - 1); ChildReports currReport = sortedReports.get(i); LocalDate prevDate = prevReport.getDate(); LocalDate currDate = currReport.getDate(); BigDecimal fillAmount = prevReport.getAmount(); int targetDay = prevDate.getDayOfMonth(); // 生成从prevDate下一个月到currDate前一个月的所有日期 LocalDate currentFillDate = prevDate.plusMonths(1); while (currentFillDate.isBefore(currDate)) { // 处理当月无目标日的情况(如2月无30号),自动调整为当月最后一天 LocalDate fillDate = adjustDayIfNeeded(currentFillDate, targetDay); filledReports.add(ChildReports.builder() .date(fillDate) .amount(fillAmount) .build()); currentFillDate = currentFillDate.plusMonths(1); } // 添加当前原始记录 filledReports.add(currReport); } return filledReports; } // 辅助方法:调整日期的日,避免月份天数不足的问题 private LocalDate adjustDayIfNeeded(LocalDate date, int targetDay) { int maxDayInMonth = date.lengthOfMonth(); return date.withDayOfMonth(Math.min(targetDay, maxDayInMonth)); }
代码逻辑说明
- 排序原始数据:确保数据按日期从小到大排列,避免原始数据顺序混乱导致填充错误。
- 初始化结果列表:先加入第一条原始记录作为填充的起始基准。
- 遍历相邻记录:针对每一对相邻的原始记录,生成它们之间所有月份的补全记录:
- 补全日期从原始前一条记录的下一个月开始,到当前原始记录的前一个月结束。
- 补全日期保持与前一条记录的日一致,若当月没有该日(如31号遇到2月),自动调整为当月最后一天。
- 补全金额直接复用前一条记录的金额。
- 添加当前记录:每处理完一段区间的补全后,加入当前的原始记录,继续下一段区间的处理。
内容的提问来源于stack exchange,提问作者Alexander
相关产品推荐
相关产品推荐

