1

I have a program to read data from multiple sources, use a tournament tree to merge sort them, pack the data into blocks and output the blocks. I have implemented this as a function, which returns null when no more block is available.

DataBlock buildBlock()

Now I want to output a stream of blocks, but the only method I have found so far is Stream.generate which generates an infinite stream. My stream is of course not infinite. What is a proper way to generate a finite stream from this function?

Harper
  • 1,794
  • 14
  • 31
  • You can `limit` it. But that depends on the source of your stream. – Naman Oct 19 '19 at 16:18
  • You are right. I do not know the actual amount of data until I can read no more from the source, so I have no idea in advance how many blocks to limit – Harper Oct 19 '19 at 16:19
  • You seem to be looking for a [while loop equivalent of streams?](https://stackoverflow.com/questions/44700006/is-there-java-stream-equivalent-to-while-with-variable-assignment) – Naman Oct 19 '19 at 16:42

2 Answers2

0

If you use at least Java 9, you can apply takeWhile(Objects::nonNull) on your stream. If you use the older Java version, check out this question.

IlyaMuravjov
  • 2,352
  • 1
  • 9
  • 27
0

You can create a stream of Optional's with Stream.iterate​(T seed, Predicate<? super T> hasNext, UnaryOperator<T> next), stopping on empty. You can then call .map(Optional::get) on the stream.

Here's an example of creating a stream that tracks the cumulative sum of a list.

public static Stream<Integer> cumulativeSum(List<Integer> nums) {
    Iterator<Integer> numItr = nums.iterator();
    if (!numItr.hasNext()) {
        return Stream.of();
    }

    return Stream.iterate(
                    Optional.of(numItr.next()),
                    Optional::isPresent,
                    maybeSum -> maybeSum.flatMap(sum ->
                            numItr.hasNext() ? Optional.of(Integer.sum(sum, numItr.next())) : Optional.empty()))
            .map(Optional::get);
}

If the input list is [2, 4, 3], then the output stream will be [2, 6, 9].

(Java 8 only has Stream.iterate​(T seed, UnaryOperator<T> f), so you will have to call .takeWhile(Optional::isPresent) instead to convert the infinite stream to a finite stream.)

MikeW
  • 36
  • 4