borgr
borgr

Reputation: 25385

How to generate a stream using an index rather than the previous element?

How do I generate a stream of "new" data? Specifically, I want to be able to create data that includes functions that are not reversible. If I want to create a stream from an Array I do

Stream.of(arr)

From a collection

col.stream()

A constant stream can be made with a lambda expression

Stream.generate(() -> "constant")

A stream based on the last input (any reversible function) may be achieved by

Stream.iterate(0, x -> x + 2)

But if I want to create a more general generator (say output of whether a number is divisive by three: 0,0,1,0,0,1,0,0,1...) without creating a new class.

The main issue is that I need to have some way of inputing the index into the lambda, because I want to have a pattern, and not to be dependent on the last output of the function.

Note: someStream.limit(length) may use to stop the length of the stream, so infinite stream generator is actually what I am looking for.

Upvotes: 1

Views: 1122

Answers (2)

Holger
Holger

Reputation: 298409

If you want to have an infinite stream for a function taking an index, you may consider creating a “practically infinite” stream using

IntStream.rangeClosed(0, Integer.MAX_VALUE).map(index -> your lambda)

resp.

IntStream.rangeClosed(0, Integer.MAX_VALUE).mapToObj(index -> your lambda)

for a Stream rather than an IntStream.

This isn’t truly infinite, but there are no int values to represent indices after Integer.MAX_VALUE, so you have a semantic problem to solve when ever hitting that index.

Also, when using LongStream.rangeClosed(0, Long.MAX_VALUE).map(index -> yourLambda) instead and each element evaluation takes only a nanosecond, it will take almost three hundred years to process all elements.

But, of course, there is a way to create a truly infinite stream using

Stream.iterate(BigInteger.ZERO, BigInteger.ONE::add).map(index -> yourLambda)

which might run forever, or more likely, bail out with an OutOfMemoryError once the index can’t be presented in the heap memory anymore, if your processing ever gets that far.

Note that streams constructed using range[Closed] might be more effcient than streams constructed using Stream.iterate.

Upvotes: 4

talex
talex

Reputation: 20544

You can do something like this

    AtomicInteger counter = new AtomicInteger(0);

    Stream<Integer> s = Stream.generate(() -> counter.getAndIncrement());

Upvotes: 0

Related Questions