Вы можете использовать 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());
}
Но ни один из этих методов не будет иметь лучшей производительности, чем решение, которое у вас уже есть.