72

Is there a easy way to create a infinity stream using without external libraries?

For example in Scala:

Iterator.iterate(0)(_ + 2)
Yassin Hajaj
  • 21,337
  • 9
  • 51
  • 89
sndyuk
  • 2,720
  • 2
  • 24
  • 32

4 Answers4

106

Yes, there is an easy way:

IntStream.iterate(0, i -> i + 2);

With as usecase:

IntStream.iterate(0, i -> i + 2)
         .limit(100)
         .forEach(System.out::println);

Which prints out 0 to 198 increasing in steps of 2.

The generic method is:

Stream.iterate(T seed, UnaryOperator<T> f);

The latter may be more uncommon in usage.

Yassin Hajaj
  • 21,337
  • 9
  • 51
  • 89
skiwi
  • 66,971
  • 31
  • 131
  • 216
7

Here is an example:

PrimitiveIterator.OfInt it = new PrimitiveIterator.OfInt() {
    private int value = 0;

    @Override
    public int nextInt() {
        return value++;
    }

    @Override
    public boolean hasNext() {
        return true;
    }
};

Spliterator.OfInt spliterator = Spliterators.spliteratorUnknownSize(it,
    Spliterator.DISTINCT | Spliterator.IMMUTABLE |
    Spliterator.ORDERED | Spliterator.SORTED);

IntStream stream = StreamSupport.intStream(spliterator, false);

It's a bit verbose, as you see. To print the first 10 elements of this stream:

stream.limit(10).forEach(System.out::println);

You can ofcourse also transform the elements, like you do in your Scala example:

IntStream plusTwoStream = stream.map(n -> n + 2);

Note that there are built-in infinite streams such as java.util.Random.ints() which gives you an infinite stream of random integers.

Jesper
  • 202,709
  • 46
  • 318
  • 350
  • 2
    Given your `PrimitiveIterator.OfInt it`, a simple `IntStream.generate(it::next)` would work as well. So it even doesn’t have to be an iterator at all, e.g. `IntStream.generate(new AtomicInteger()::incrementAndGet)` will provide such a natural number sequence too. – Holger Mar 20 '14 at 10:11
  • 1
    Yes, obviously my solution is much more verbose than necessary and there are multiple ways to do it. – Jesper Mar 20 '14 at 10:52
  • Didn't know `java.util.Random.ints()`, +1 – Markus Weninger Aug 31 '16 at 07:39
4

There is another possible solution in Java 8:

AtomicInteger adder = new AtomicInteger();
IntStream stream = IntStream.generate(() -> adder.getAndAdd(2));

Important: an order of numbers is preserved only if the stream is sequential.


It's also worth noting that a new version of the IntStream.iterate has been added since Java 9:

static IntStream iterate​(int seed,
                         IntPredicate hasNext,
                         IntUnaryOperator next);
  • seed - the initial element;
  • hasNext - a predicate to apply to elements to determine when the stream must terminate;
  • next - a function to be applied to the previous element to produce a new element.

Examples:

IntStream stream = IntStream.iterate(0, i -> i >= 0, i -> i + 2);

IntStream.iterate(0, i -> i < 10, i -> i + 2).forEach(System.out::println);
Oleksandr Pyrohov
  • 14,685
  • 6
  • 61
  • 90
0

You can build your own InfiniteStream by implementing stream and consumer and compose both and may will need queue to queueing your data as :

public class InfiniteStream<T> implements Consumer<T>, Stream<T> {
private final Stream<T> stream;
private final Queueing q;
...
public InfiniteStream(int length) {
    this.q = new Queueing(this.length);
    this.stream = Stream.generate(q);
    ...
}
    //implement stream methods
    //implement accept
}

check full code here https://gist.github.com/bassemZohdy/e5fdd56de44cea3cd8ff

Bassem Reda Zohdy
  • 12,662
  • 3
  • 33
  • 39