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

使用groupingBy计算有序Round列表相邻元素的日期差值

按日期分组计算Round对象的天数差值

需求说明

现有已排序的Round对象列表,每个对象包含number、beginDate字段,需为其设置differenceDaysNumber字段,规则如下:

  • 按beginDate对Round元素分组,每组内所有元素共享同一个differenceDaysNumber值
  • 该值为当前组的beginDate与下一个组的beginDate的天数差值
  • 最后一组的元素differenceDaysNumber设为null

要求使用Stream的groupingBy方法(或更优方案)实现。

相关代码定义

Round类

@Builder
@Getter
public class Round {
    Integer number;
    LocalDateTime beginDate;
    @Setter
    Integer differenceDaysNumber;
}

待补充逻辑的代码片段

var result = seriesInfoList.stream()
        .collect(Collectors.groupingBy(Round::getBeginDate));  // what next ?

输入示例

List<Round> input = List.of(
        new Round(1, LocalDateTime.of(2020, 12, 1, 12, 12, 12, 12), null),
        new Round(1, LocalDateTime.of(2020, 12, 11, 12, 12, 12, 12), null),
        new Round(2, LocalDateTime.of(2020, 12, 11, 12, 12, 12, 12), null),
        new Round(3, LocalDateTime.of(2020, 12, 11, 12, 12, 12, 12), null),
        new Round(1, LocalDateTime.of(2020, 12, 17, 12, 12, 12, 12), null),
        new Round(1, LocalDateTime.of(2020, 12, 12, 12, 12, 12, 12), null));

预期输出示例

List<Round> output = List.of(
        new Round(1, LocalDateTime.of(2020, 12, 1, 12, 12, 12, 12), 10),
        new Round(1, LocalDateTime.of(2020, 12, 11, 12, 12, 12, 12), 6),
        new Round(2, LocalDateTime.of(2020, 12, 11, 12, 12, 12, 12), 6), // 同日期元素共享差值
        new Round(3, LocalDateTime.of(2020, 12, 11, 12, 12, 12, 12), 6), // 同日期元素共享差值
        new Round(1, LocalDateTime.of(2020, 12, 17, 12, 12, 12, 12), 5),
        new Round(1, LocalDateTime.of(2020, 12, 12, 12, 12, 12, 12), null));

解决方案

由于groupingBy默认返回无序的HashMap,无法保证分组顺序,因此需要用TreeMap来维持beginDate的升序排列,确保能正确找到下一个组的日期。具体实现步骤如下:

  1. 按日期分组并保持顺序:通过groupingBy的重载方法指定TreeMap作为容器,自动按LocalDateTime排序分组。
  2. 提取有序日期列表:从TreeMap中获取所有日期键,形成有序列表。
  3. 遍历计算并设置差值:对每个日期组,计算与下一组日期的天数差,批量设置到组内元素;最后一组设置为null。
  4. 输出结果:由于修改的是原对象引用,原列表已更新,可直接使用;若需按日期顺序输出,合并分组即可。

完整实现代码

import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.stream.Collectors;

public class RoundProcessor {
    public static void main(String[] args) {
        List<Round> input = List.of(
                new Round(1, LocalDateTime.of(2020, 12, 1, 12, 12, 12, 12), null),
                new Round(1, LocalDateTime.of(2020, 12, 11, 12, 12, 12, 12), null),
                new Round(2, LocalDateTime.of(2020, 12, 11, 12, 12, 12, 12), null),
                new Round(3, LocalDateTime.of(2020, 12, 11, 12, 12, 12, 12), null),
                new Round(1, LocalDateTime.of(2020, 12, 17, 12, 12, 12, 12), null),
                new Round(1, LocalDateTime.of(2020, 12, 12, 12, 12, 12, 12), null));

        // 按beginDate分组,用TreeMap保证时间升序
        Map<LocalDateTime, List<Round>> groupedRounds = input.stream()
                .collect(Collectors.groupingBy(
                        Round::getBeginDate,
                        TreeMap::new,
                        Collectors.toList()));

        // 获取排序后的日期列表
        List<LocalDateTime> sortedDates = new ArrayList<>(groupedRounds.keySet());

        // 计算并设置差值
        for (int i = 0; i < sortedDates.size(); i++) {
            LocalDateTime currentDate = sortedDates.get(i);
            List<Round> currentGroup = groupedRounds.get(currentDate);

            if (i < sortedDates.size() - 1) {
                LocalDateTime nextDate = sortedDates.get(i + 1);
                // 计算日期部分的天数差,忽略时分秒
                long daysDiff = ChronoUnit.DAYS.between(currentDate.toLocalDate(), nextDate.toLocalDate());
                currentGroup.forEach(round -> round.setDifferenceDaysNumber((int) daysDiff));
            } else {
                currentGroup.forEach(round -> round.setDifferenceDaysNumber(null));
            }
        }

        // 验证输出(原顺序)
        input.forEach(round -> System.out.printf(
                "number: %d, beginDate: %s, differenceDaysNumber: %s%n",
                round.getNumber(), round.getBeginDate(), round.getDifferenceDaysNumber()));
    }
}

// Round类定义
@Builder
@Getter
class Round {
    Integer number;
    LocalDateTime beginDate;
    @Setter
    Integer differenceDaysNumber;

    // 全参构造函数,配合示例使用
    public Round(Integer number, LocalDateTime beginDate, Integer differenceDaysNumber) {
        this.number = number;
        this.beginDate = beginDate;
        this.differenceDaysNumber = differenceDaysNumber;
    }
}

关键说明

  • TreeMap的作用:确保分组按LocalDateTime升序排列,保证下一组日期的正确性。
  • 天数差计算:使用ChronoUnit.DAYS.between并转换为LocalDate,避免时分秒对天数计算的干扰。
  • 引用修改:由于Java对象是引用类型,修改分组内的元素会直接更新原列表中的对象,无需额外复制操作。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 00:24:54