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 是否有更好的东西,或者我可以按连续天数对日期进行分组,然后使用间隔收集它们
基于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)