Flattening a list of items in Java 8 Additional pipeline
I have a value id
that can be null
. Then I need to call some service using this id
to get the list of trades and get the first trade null
from the list.
I currently have this working code
Optional.ofNullable(id)
.map(id -> service.findTrades(id))
.flatMap(t -> t.stream().filter(Objects::nonNull).findFirst())
.orElse(... default value...);
Is it possible to implement a more elegant line with a call flatMap
? I don't want to put a lot of logic in one stage of the pipeline.
Originally I expected to implement the logic this way
Optional.ofNullable(id)
.flatMap(id -> service.findTrades(id))
.filter(Objects::nonNull)
.findFirst()
.orElse(... default value...);
But it Optional.flatMap
does not allow the list to be flattened into many of its elements.
source to share
I don't know if it's elegant or not, but here's a way to convert the optional in a stream before the streaming pipeline starts:
Trade trade = Optional.ofNullable(id)
.map(service::findTrades)
.map(Collection::stream)
.orElse(Stream.empty()) // or orElseGet(Stream::empty)
.filter(Objects::nonNull)
.findFirst()
.orElse(... default value...);
In Java 9 will have a method , so you will be able to directly convert the optional to a stream Optional
.stream()
Trade trade = Optional.ofNullable(id)
.stream() // <-- Stream either empty or with the id
.map(service::findTrades) // <-- Now we are at the stream pipeline
.flatMap(Collection::stream) // We need to flatmap, so that we
.filter(Objects::nonNull) // stream the elements of the collection
.findFirst()
.orElse(... default value...);
source to share
There is a better way to do this with StreamEx
StreamEx.ofNullable(id)
.flatMap(id -> service.findTrades(id))
.filter(Objects::nonNull)
.findFirst()
.orElse(... default value...);
I just saw, " As Stuart Marks says, Rule # 4: It is generally a bad idea to create optional purpose-specific chaining methods from it in order to get the value .. " in the comments under another question :
source to share