Java Joy: Infinite Stream Of Values Or Method Invocations
In Java we can use the generate
method of the Stream
class to create an infinite stream of values. The values are coming from a Supplier
instance we pass as argument to the generate
method. The Supplier
instance usually will be a lambda expression. To give back a fixed value we simply implement a Supplier
that returns the value. We can also have different values when we use a method that returns a different value on each invocation, for example the randomUUID
method of the UUID
class. When we use such a method we can create the Supplier
as method reference: UUID::randomUUID
.
The generate
method returns an unbounded stream. We must use methods like limit
and takeWhile
to get a bounded stream again. We must use findFirst
or findAny
to terminate the unbounded stream and get a value.
In the following example we use the generate
method with a Supplier
that returns a repeating fixed String
value and some different values from invoking the now
method of LocalTime
:
package mrhaki.stream;
import java.time.LocalTime;
import java.util.List;
import java.util.stream.Stream;
import static java.util.stream.Collectors.toUnmodifiableList;
public class Generate {
public static void main(String[] args) {
// Create a infinite stream where each item is the string value "Java".
// We let the supplier function return a fixed value "Java".
assert Stream.generate(() -> "Java")
.limit(4)
.collect(toUnmodifiableList()).equals(List.of("Java", "Java", "Java", "Java"));
// Create an infinite stream of function invocations of LocalTime.now().
// The supplier function returns a different value for each invocation.
var currentTimes = Stream.generate(LocalTime::now)
.limit(2)
.collect(toUnmodifiableList());
assert currentTimes.get(0).isBefore(currentTimes.get(1));
// Create a list of 100 time values where each value should be later than the next.
var timeSeries = Stream.generate(LocalTime::now).limit(100).collect(toUnmodifiableList());
assert latestTime(timeSeries).equals(timeSeries.get(timeSeries.size() - 1));
}
/**
* Get the latest time from a serie of time values.
*
* @param times List with time values.
* @return Latest time value from the collection.
*/
private static LocalTime latestTime(List<LocalTime> times) {
return times.stream().reduce((acc, time) -> {
if (acc.isAfter(time)) { return acc; } else { return time; }
}).get();
}
}
Written with Java 14.