An infinite stream in Java 8 is created with Stream.iterate() or Stream.generate(), both of which produce an unbounded sequence of elements that must be constrained with a short-circuiting operation like limit() before being consumed.
Key Points: • Stream.iterate(seed, UnaryOperator<T>) generates each next element by applying the function to the previous element. • Stream.generate(Supplier<T>) generates each element independently by repeatedly invoking the supplier. • Because these streams have no defined end, calling a terminal operation like collect() or forEach() directly on them would run forever (or until memory/resources are exhausted). • limit(n) is the standard way to bound an infinite stream to a usable, finite size before a terminal operation runs. • Java 9 added an overloaded Stream.iterate(seed, hasNext, next) that includes its own termination predicate, making limit() unnecessary in that version.
Example: Stream.iterate(0, n -> n + 1).limit(10).forEach(System.out::println) prints the numbers 0 through 9, generated lazily one at a time.
Code Example:
Stream.iterate(0, n -> n + 1)
.limit(10)
.forEach(System.out::println);
Stream.generate(Math::random)
.limit(5)
.forEach(System.out::println);Interview Tip: A concise interview answer is:
"I use Stream.iterate() when each element depends on the previous one, like counting up or computing powers of two, and Stream.generate() when each element is produced independently, like random numbers. Both produce infinite streams, so I always chain a limit() call before a terminal operation, otherwise the pipeline never finishes."