✍️Stream.iterate in Java 8
When we talk about Java 8 Streams, one of the hidden gems is the Stream.iterate()
method. It’s not as commonly used as map()
or filter()
, but it can be incredibly powerful for generating sequences and creating custom data flows.
In this post, let’s explore how Stream.iterate()
works and walk through some practical examples that can make your code both elegant and functional.
What is Stream.iterate()
?
In Java 8, the Stream.iterate()
method lets you create a stream of values starting from an initial value and applying a function to get the next value.
It’s like saying:
“Start from this number, then keep applying this rule to get the next numbers.”
Here’s the syntax of Stream.iterate
static <T> Stream<T> iterate(T seed, UnaryOperator<T> f)
seed
: The initial value or starting point of the stream.f
: The unary operator (a function that takes one argument and returns a result of the same type) to apply to the previous element to produce the next element.
Here’s an example of using Stream.iterate
in Java 8:
Example 1: Generate 10 even numbers
Stream.iterate(0, n -> n + 2)
.limit(10)
.forEach(System.out::println);
What it does:
- Start with
0
- Add
2
each time: 0, 2, 4, 6, ... - Take only 10 numbers
- Print them one by one
Output:
0
2
4
6
8
10
12
14
16
18
Example 2: Generate 10 numbers starting from 3, increase by 3
Stream.iterate(3, n -> n + 3)
.limit(10)
.forEach(System.out::println);
Output:-
3
6
9
12
15
18
21
24
27
30
Example 3: Generate Powers of 2
Stream.iterate(1, n -> n * 2)
.limit(10)
.forEach(System.out::println);
Output:-
1
2
4
8
16
32
64
128
256
512
Example 4: Create a Multiplication Table
int number = 7;
Stream.iterate(1, n -> n + 1)
.limit(10)
.map(n -> n * number)
.forEach(System.out::println);
💥 Boom! You’ve got a multiplication table for 7.
Example 5: Use takeWhile
to stop when a condition is false (Java 9+)
Stream.iterate(1, n -> n + 1)
.takeWhile(n -> n < 10)
.forEach(System.out::println);
Output:-
1
2
3
4
5
6
7
8
9
Note: takeWhile()
is only available from Java 9 and up.
⚠️ Note: Infinite Streams
Stream.iterate()
generates an infinite stream unless you explicitly stop it with something like limit()
. Always make sure to do that—or you might end up freezing your app with an endless loop.
💡 Java 9 Upgrade
Java 9 enhanced Stream.iterate()
with a new overloaded version:
Stream.iterate(seed, predicate, unaryOperator)
This one lets you generate a finite stream without calling limit()
:
Stream.iterate(0, n -> n < 10, n -> n + 2)
.forEach(System.out::println);
✅ Much cleaner when you want a bounded stream with a condition!
📌 Wrapping Up
Stream.iterate()
is a functional way to replace traditional for
loops, perfect for generating sequences or doing computations in a cleaner and more declarative style.
Try experimenting with it in your own utility methods or data pipelines — once you get the hang of it, you’ll appreciate how expressive and concise your code can become.
🧠 Bonus Tip
Combine iterate()
with other stream operations like map()
, filter()
, and collect()
to build powerful data transformations in just a few lines of code.
🧠 Summary
Stream.iterate()
creates a stream of values based on a rule.- Use
limit()
to control how many values you want. - In Java 9+, you can also use
takeWhile()
to stop when a condition is false.
Tricky interview questions on Stream.iterate()
that have been asked in MNC interviews
1. What is Stream.iterate
in Java 8?
Stream.iterate
is a method introduced in Java 8 that generates an infinite stream of values based on an initial seed and a function.
2. How do you use Stream.iterate
to generate a sequence of numbers?
- Provide an example of using
Stream.iterate
to generate a sequence of numbers, explaining the seed value and the function.
3. What is the purpose of the second parameter (UnaryOperator) in Stream.iterate
?
- The second parameter is a function (UnaryOperator) that defines how each element of the stream is generated based on the previous one.
4. How do you limit the number of elements in the stream generated by Stream.iterate
?
- Use the
limit
method to restrict the number of elements in the stream.
5. How do you generate a finite stream of even numbers using Stream.iterate()
without using limit()
?
Expected Answer:
In Java 9+, you can use the three-parameter version of Stream.iterate()
:
Stream.iterate(0, n -> n < 20, n -> n + 2)
.forEach(System.out::println);
👉 This avoids infinite streams and is cleaner than using limit()
.
6. How would you use Stream.iterate()
to generate the Fibonacci sequence?
Stream.iterate(new int[]{0, 1}, n -> new int[]{n[1], n[0] + n[1]})
.limit(10)
.map(n -> n[0])
.forEach(System.out::println);
👉 Trick here is using array tuples to hold previous values.
7. What’s the risk of using Stream.iterate()
and how do you avoid it?
The main risk is creating an infinite stream, which can cause memory or CPU issues.
✅ To avoid this:
- Use
.limit()
in Java 8 - Or use the 3-argument
Stream.iterate()
in Java 9+
8. Can you use Stream.iterate()
to generate a sequence of dates (e.g., next 7 days)?
LocalDate start = LocalDate.now();
Stream.iterate(start, date -> date.plusDays(1))
.limit(7)
.forEach(System.out::println);
👉 This tests your understanding of using streams with LocalDate
.
9. What is the difference between Stream.iterate()
and IntStream.range()
? When should you prefer one over the other?
Stream.iterate()
is more flexible for non-linear or dynamic sequences.IntStream.range()
is better for simple numeric ranges, better performance (primitive streams), and avoids boxing/unboxing.
Use IntStream.range()
for numeric loops, use Stream.iterate()
when each element depends on the previous.
10. Write code using Stream.iterate()
to print all odd numbers between 1 and 50 (inclusive).
Stream.iterate(1, n -> n <= 50, n -> n + 2)
.forEach(System.out::println);
👉 Tests ability to work with conditions in Java 9+ style.
11. Is Stream.iterate()
parallelizable? What’s the catch?
It can be parallelized using .parallel()
, but not efficiently.
⚠️ Since each element depends on the previous one, iterate()
is inherently sequential. Using .parallel()
may not give performance benefits and can be misleading.
12. Can you generate prime numbers using Stream.iterate()
?
This is intentionally tricky since prime number logic is complex.
Hinted Answer:
Yes, but you need to combine Stream.iterate()
with a filter()
:
Stream.iterate(2, n -> n + 1)
.filter(StreamIterateExample::isPrime)
.limit(10)
.forEach(System.out::println);
public static boolean isPrime(int number) {
return IntStream.rangeClosed(2, (int)Math.sqrt(number))
.allMatch(n -> number % n != 0);
}
13. What’s the difference between Stream.generate()
and Stream.iterate()
?
Stream.generate(Supplier)
→ generates random/independent elementsStream.iterate(seed, unaryOperator)
→ generates dependent elements (each based on previous)
Use generate()
for randomness (like UUID.randomUUID()
), use iterate()
for sequences.
14. How to use Stream.iterate()
to implement a custom for-loop (like for(int i=5; i<=50; i+=5)
)
Stream.iterate(5, n -> n <= 50, n -> n + 5)
.forEach(System.out::println);
👉 This mimics a classic for
loop in functional style.
Thanks & Happy Learning