Как использовать Java Stream с пустым списком - PullRequest
1 голос
/ 05 апреля 2019

Мне нужно использовать Java Stream в этом коде, но я не знаю, как это работает с пустым списком.

Я пытаюсь найти что-то вроде while в Stream Java 8, но не могу его найти.

public static List<DateBucket> bucketize(ZonedDateTime fromDate, ZonedDateTime toDate, int bucketSize, ChronoUnit bucketSizeUnit) {

    List<DateBucket> buckets = new ArrayList<>();;
    boolean reachedDate = false;

    for (int i = 0; !reachedDate; i++) {
        ZonedDateTime minDate = fromDate.plus(i * bucketSize, bucketSizeUnit);
        ZonedDateTime maxDate = fromDate.plus((i + 1) * bucketSize, bucketSizeUnit);
        reachedDate = toDate.isBefore(maxDate);
        buckets.add(new DateBucket(minDate.toInstant(), maxDate.toInstant()));
    }

    return buckets;
}

Я ожидаю избежать for и использовать Stream в основной части кода.

1 Ответ

2 голосов
/ 05 апреля 2019

Вы можете использовать LongStream для запуска и mapToObj() для создания DateBucket s:

public static List<DateBucket> bucketize(ZonedDateTime fromDate, ZonedDateTime toDate, int bucketSize, ChronoUnit bucketSizeUnit) {
    return LongStream.rangeClosed(0, bucketSizeUnit.between(fromDate, toDate))
            .mapToObj(i -> {
                ZonedDateTime minDate = fromDate.plus(i * bucketSize, bucketSizeUnit);
                ZonedDateTime maxDate = fromDate.plus((i + 1) * bucketSize, bucketSizeUnit);
                return new DateBucket(minDate.toInstant(), maxDate.toInstant());
            })
            .filter(b -> {
                ZonedDateTime maxDate = b.getMaxDate().atZone(toDate.getZone());
                ZonedDateTime limitDate = toDate.plus(bucketSize, bucketSizeUnit);
                return maxDate.isBefore(limitDate) || maxDate.isEqual(limitDate);
            })
            .collect(Collectors.toList());
}

Это создает IntStream от 0 до максимально возможного индекса между указанными датами, сопоставляет каждый индекс с DateBucket и фильтрует результат для требуемого диапазона.

Если вы можете использовать Java 9 , я бы рекомендовал использовать IntStream.iterate() вместо Intstream.rangeClosed() и takeWhile() вместо filter():

public static List<DateBucket> bucketize(ZonedDateTime fromDate, ZonedDateTime toDate, int bucketSize, ChronoUnit bucketSizeUnit) {
    return LongStream.iterate(0, i -> i + 1)
            .mapToObj(i -> {
                ZonedDateTime minDate = fromDate.plus(i * bucketSize, bucketSizeUnit);
                ZonedDateTime maxDate = fromDate.plus((i + 1) * bucketSize, bucketSizeUnit);
                return new DateBucket(minDate.toInstant(), maxDate.toInstant());
            })
            .takeWhile(b -> {
                ZonedDateTime maxDate = b.getMaxDate().atZone(toDate.getZone());
                ZonedDateTime limitDate = toDate.plus(bucketSize, bucketSizeUnit);
                return maxDate.isBefore(limitDate) || maxDate.isEqual(limitDate);
            })
            .collect(Collectors.toList());
}

Но ни один из этих методов не будет иметь лучшей производительности, чем решение, которое у вас уже есть.

...