list.stream().filter(Objects::nonNull)
.map(User::getUsername).filter(Objects::nonNull)
.findFirst(name -> name.contains(searchString))
.map(name -> “We have found your user: “ + name)
.orElse(“We haven’t found”);the point I wanted to make is that the snippets presented seem carefully crafted to make pipelines look bad, but usually that's not the case.
Intermediate stream operations like map or filter are always lazy. And .findFirst() is a short-circuiting terminal operation, that does not need to consume all stream elements.
https://docs.oracle.com/en/java/javase/11/docs/api/java.base...
Truth is java streams and, even more, reactive java are the only two things that make java bearable, god save who invented them.
If I had to program java with for loops and list.add or null checks everywhere, I would probably kill myself on the spot.
But the amount of programmers taught to program like it's still 1995 it's so damn high
And I am closer to my 50s than my 40s, I can't understand why people fresh from uni say they can't understand something like
list.stream()
.map(this::maybeGetUser)
.filter(maybeUser -> userIsPresentAndNameStartsWith(maybeUser, prefix))
.findFirst()
.orElseThrow(new UserNotFoundException());
with the benefit of being lazy and only inspecting list items up to the first one that matches (and if you don't mutate any data, easily parallelizable)
In a list
searching for "Jo" returns all three of them in the first example, it stops when the first has been found in the second.Start including the tedious bits about adding found items to the list and the waste of intermediate variables and your "clear" code is wrapped around a lot of repetitions, that only add noise.
It just happens that you are more familiar with the second style, but pipelines are better in many other ways, clarity of intentions being one of them.