从 Java 中的一系列日期中获取所有连续间隔的列表

San*_*air 8 java date java-8 java-stream

我有一个 LocalDates 列表,比如 14-06-2020、15-06-2020、17-06-2020、19-06-2020、20-06-2020、21-06-2020,我想要所有连续的以上日期的间隔。所以输出会像

Interval 1 = [14-06-2020, 15-06-2020]
Interval 2 = [17-06-2020, 17-06-2020]
Interval 3 = [19-06-2020, 21-06-2020]
Run Code Online (Sandbox Code Playgroud)

在 Java 中最有效的方法是什么

所以我创建了一个 Interval 类来保存开始和结束日期

public class Interval{
  private LocalDate startDate;
  private LocalDate endDate;
}
Run Code Online (Sandbox Code Playgroud)

我可以遍历日期列表中的每个元素,然后检查逻辑是否两个日期在下面的行中是连续的,

public static void main(String args[]){
    List<LocalDate> dates = new ArrayList<>();
    dates.add(LocalDate.of(2020,6,14));
    dates.add(LocalDate.of(2020,6,15));
    dates.add(LocalDate.of(2020,6,17));
    dates.add(LocalDate.of(2020,6,19));
    dates.add(LocalDate.of(2020,6,21));
    dates.add(LocalDate.of(2020,6,20));

    Collections.sort(dates);

    //Handle if empty or null
    List<Interval> intervals = new ArrayList<>();
    if(dates==null || dates.size()==0){
        throw new IllegalArgumentException("list cannot be empty");
    }

    //If only one date then the interval starts and ends with same date
    if(dates.size()==1){
        Interval interval = new Interval();
        interval.setStartDate(dates.get(0));
        interval.setEndDate(dates.get(0));
    }
    LocalDate firstDate = dates.get(0);

    for(int i =1;i<dates.size(); i++){
        LocalDate endDate = dates.get(i);
        LocalDate nextDate = endDate.plusDays(1);
        //iterate over to get the desired list of interval
        while(my condition satisfies){
            //create new interval
        }
        //intervals.add(interval
    }
}
Run Code Online (Sandbox Code Playgroud)

我想检查使用流 api 是否有更好的东西,或者我可以按连续天数对日期进行分组,然后使用间隔收集它们

Nam*_*man 5

基于Stream排序集合的方法的“解决方法”可能是使用标记进行范围查找 -

List<Integer> rangeMarkers = new ArrayList<>();
rangeMarkers.add(0);
rangeMarkers.addAll(IntStream.range(0, dates.size() - 1)
        .filter(i -> !dates.get(i).plusDays(1).equals(dates.get(i + 1)))
        .mapToObj(i -> i + 1)
        .collect(Collectors.toList()));
rangeMarkers.add(dates.size());
System.out.println(rangeMarkers);
Run Code Online (Sandbox Code Playgroud)

然后使用这些标记将日期映射到Interval-

List<Interval> intervals = IntStream.range(0, rangeMarkers.size() - 1)
        .mapToObj(i -> new Interval(dates.get(rangeMarkers.get(i)),
                dates.get(rangeMarkers.get(i + 1) - 1)))
        .collect(Collectors.toList());
System.out.println(intervals);
Run Code Online (Sandbox Code Playgroud)