我的id
值可以是null
。然后我需要使用此id
调用某个服务来获取交易列表,并从列表中获取第一个非null
交易。
目前我有这个工作代码
Optional.ofNullable(id)
.map(id -> service.findTrades(id))
.flatMap(t -> t.stream().filter(Objects::nonNull).findFirst())
.orElse(... default value...);
是否可以更优雅地实施flatMap
来电?我不想在一个管道步骤中加入太多逻辑。
最初我希望以这种方式实现逻辑
Optional.ofNullable(id)
.flatMap(id -> service.findTrades(id))
.filter(Objects::nonNull)
.findFirst()
.orElse(... default value...);
但是Optional.flatMap
不允许将列表展平为一组元素。
答案 0 :(得分:9)
我不知道这是否优雅,但这是在启动流管道之前在流中转换可选项的方法:
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...);
在Java 9中,Optional
will have a .stream()
method,因此您可以直接将可选项转换为流:
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...);
答案 1 :(得分:3)
StreamEx.ofNullable(id)
.flatMap(id -> service.findTrades(id))
.filter(Objects::nonNull)
.findFirst()
.orElse(... default value...);
我刚看到As Stuart Marks says it, Rule #4: It's generally a bad idea to create an Optional for the specific purpose of chaining methods from it to get a value..下的评论中的“another question”: