我需要在此代码中使用Java Stream,但我不知道如何使用空列表。
我试图在 Stream Java 8 中找到类似while
的东西,但我找不到它。
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。
LongStream
开始和mapToObj()
来创建DateBucket
:
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());
}
这将创建一个从给定日期之间的0
到最大可能索引的 IntStream,将每个索引映射到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());
}
但是,这些方法都不会比您已有的解决方案具有更好的性能。
用Stream.iterate
来生成一个列表,你需要提供两个参数,第一个是初始参数,第二个是处理上一个参数并返回下一个参数的函数:
public static List<DateBucket> bucketize(ZonedDateTime fromDate, ZonedDateTime toDate, int bucketSize, ChronoUnit bucketSizeUnit) {
List buckets = Stream.iterate(
new DateBucket(
fromDate.toInstant(),
fromDate.plus(bucketSize, bucketSizeUnit).toInstant()
),
(DateBucket db) -> new DateBucket(db.to, db.to.plus( bucketSize, bucketSizeUnit))
)
.limit(bucketSizeUnit.between(fromDate, toDate) / bucketSize)
.collect(Collectors.toList());
return buckets;
}