Infinite Streams in Java
Why Infinite Streams?
Infinite streams may seem like an odd thing at first, but iterating over something for an infinite amount of time is not uncommon in programming. How many times have you seen the following code or written it yourself?
while (true) {
// ...
}
This isn't to be confused with something like an infinite loop that causes a program to crash. Infinite loops are used to do something until a condition is met and then break out. An infinite stream is used the same way but is done using a stream instead of a loop. Using an infinite loop, you may do something like the following:
while (true) {
// ...
if (isProcessed()) {
break;
}
}
It is an infinite loop but can still stop the execution when a certain condition is met. This same concept is done in infinite streams but using the limit() method.
Creating Infinite Streams
When creating infinite streams, it is important to use limit(). Without using the limit() method, your stream will crash the program the same way an unintended infinite loop would. There are two different ways of generating infinite streams depending on if the order matters or not.
Infinite Streams Using iterate()
The iterate() method is used to create an ordered infinite stream. The method signature for iterate() is the following:
public static <T> Stream<T> iterate(T seed, UnaryOperator<T> f)
This takes a seed as the first parameter and an UnaryOperator as the second parameter. An example using ints would be the following:
final List<Integer> numbers = Stream.iterate(1, i -> i + 1)
.limit(10)
.toList();
This would generate an infinite stream with a seed of 1. This takes the stream and converts it to a List. This has a limit() of 10 and would generate a List with the numbers [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].
Using an infinite while loop, this same thing would look like the following:
final var numbers = new ArrayList<Integer>();
int number = 0;
while (true) {
numbers.add(++number);
if (number == 10) {
break;
}
}
Infinite Streams Using generate()
The generate() method is used to create an unordered infinite stream. The method signature for generate() is the following:
public static <T> Stream<T> generate(Supplier<T> s)
This takes a Supplier as a method. This can be used to generate anything such as an object, a UUID, an integer, etc. The following example shows an infinite stream generated with random numbers. The stream has a limit of 10 and converts the Stream to a List.
final List<Integer> randomNumber = Stream.generate(
() -> new Random().nextInt(10)
)
.limit(10)
.toList();
This will generate 10 random numbers in a List with 10 elements.
Conclusion
Infinite streams are similar to infinite loops but use a stream instead. Make sure you use limit(). Without this, you will crash your program, similar to an infinite loop.