Java 8 Stream of LocalDateTime,如何在不循环全部的情况下找到它们的列表

时间:2019-03-10 11:24:35

标签: java filter java-8 java-stream

我有一个Java 8 LocalDateTime(时间戳)的列表/流,它按升序(时间顺序)。

2019-03-01T13:13:13
2019-03-01T15:15:15
2019-03-02T12:12:12
2019-03-02T14:14:14
2019-03-03T11:11:11
2019-03-03T08:08:08

如何快速找到给定12小时内的子列表,而不循环查看列表的所有元素。我知道只是做一个过滤器会很简单,但是会循环整个列表(假设列表很大)

如果开始时间戳为2019-03-01T10:10:10,则结束时间戳为2019-03-01T22:22:21

时间戳子列表必须在开始之后和结束之前。

3 个答案:

答案 0 :(得分:0)

您可以尝试查看列表的两端,对索引进行计数,直到找到等于或小于所需开始时间的第一个索引,然后向后迭代以获取所需时间段中最后一次的索引。 像这样:

int first;
for (LocalDateTime time : timeStampList){
    if (time.compareTo(startTime) < 0){
        first++;
    }else{
        return i + 1;
    }
}

int last = list.length();
while (last > 0){
    LocalDateTime time = timeStampList[last];
    if (time.compareTo(endTime) > 0){
        last -= 1;
    }else{
       return last - 1;
    }
}

您要查找的子集将是这些索引之间(包括两端)的所有内容

答案 1 :(得分:0)

您可以使用NavigableSet的{​​{3}}方法

  

NavigableSet subSet(E fromElement,                          来自Inclusive的布尔值,                          E toElement,                          boolean toInclusive)

可能是这样的:

NavigableSet<LocalDateTime> treeSet = new TreeSet<>(yourListWithTimestamps);

//Initialize your start and end date-times:
LocalDateTime start = LocalDateTime.parse("2019-03-01T10:10:10");
LocalDateTime end = LocalDateTime.parse("2019-03-01T22:22:21");

NavigableSet<LocalDateTime> subSet = treeSet.subSet(start, false, end, false);

//Optional - convert it back to list:
List<LocalDateTime> subList = new ArrayList<>(subSet);

答案 2 :(得分:0)

我可以为您建议以下根本不使用drop的代码:

import java.time.Duration;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;
import java.util.function.BiPredicate;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

public class SublistWithLambda {

    public static void main(String[] args) {
        List<LocalDateTime> dates = Arrays.asList(
                LocalDateTime.now().minusHours(24),
                LocalDateTime.now().minusHours(22),
                LocalDateTime.now().minusHours(20),
                LocalDateTime.now().minusHours(12),
                LocalDateTime.now().minusHours(10),
                LocalDateTime.now().minusHours(7),
                LocalDateTime.now().minusHours(5)
        );

        BiPredicate<LocalDateTime, LocalDateTime> isLessThan12Hours = (date1, date2) -> {
            Duration duration = Duration.between(date2, date1);
            return duration.toHours() >= 0 && duration.toHours() <= 12;
        };

        List<List<LocalDateTime>> result = IntStream
                .range(0, dates.size())
                .mapToObj(i -> dates.stream().skip(i)
                        .takeWhile(date -> isLessThan12Hours.test(date, dates.get(i)))
                        .collect(Collectors.toList()))
                .collect(Collectors.toList());

        result.forEach(System.out::println);
    }
}

我希望这就是您想要的。