Why doesn’t my Java Stream do anything?
Chances are you forgot to terminate it.
Java is a programming language which has been able to stream objects and actions since version 1.8. Streaming is very useful for moving larger amounts of data. But after setting up all your maps, filters, reduces, and peeks, you may find that nothing is actually getting done.
Why?
Java streams are lazy.
They won’t do anything unless they get terminated. A terminating operation activates everything else that should be happening in the stream. No termination: no action.
An example
final Stream.Builder<String> b = Stream.builder();
b.accept("hello");
b.accept("world");
final Stream<String> xs = b.build();
var initials = xs.filter(x -> !x.isEmpty())
.map(x -> x.substring(1))
.map(String::toUpperCase)
.peek(x -> System.out.println(x));
This sets up a stream and then declares the operations that should happen to the data streaming through it. Those operations do not actually happen. Not even the logging. All we did was declare our intent: we want them to happen.
This concept is called, declarative programming.
We still need to make the actions happen. To do that, we add what the Java programming language calls a terminating operation. For instance, the collect operation:
var initials = xs.filter(x -> !x.isEmpty())
.map(x -> x.substring(1))
.map(String::toUpperCase)
.collect(Collectors.joining(", "));
That will have the desired effect: now all the operations will happen.
So next time you wonder why none of your streaming operations do anything, but you also don’t get any error messages nor any logging:
Remember to kick it.
About the author
Veltstra is a very experienced software architect and engineer, who will forget constructs used rarely, and shares that experience with the world if it seems like the internet does not yet know about it, so you don’t have to spend hours debugging something that isn’t broken in the first place.