Aldo Fernando Saia
Aldo Fernando Saia

Reputation: 69

How to use Java Stream with empty list

I need to use Java Stream in this code, but I don't know how it to work with an empty list.

I'm trying to find something like a while in Stream Java 8, but I can't find it.

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;
}

I expect to avoid the for and use Stream in the major portion of code.

Upvotes: 1

Views: 1205

Answers (2)

ton
ton

Reputation: 4577

You need to use Stream.iterate to generate a list, you need to provide two args, the first is a initial argument, and the second is a function to process the previous argument and return the next one:

        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;
        }

Upvotes: 0

Samuel Philipp
Samuel Philipp

Reputation: 11042

You can use a LongStream to start and mapToObj() to create your DateBuckets:

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());
}

This creates an IntStream from 0 to the max possible index between the given dates, maps each index to a DateBucket and filters the result for the required range.

If you can use Java 9 I would recommend using IntStream.iterate() instead of Intstream.rangeClosed() and takeWhile() instead of 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());
}

But none of this methods will have a better performance than the solution you already have.

Upvotes: 3

Related Questions