问题描述
新的Java 8流框架和朋友们提供了一些非常简洁的Java代码,但是我遇到了一个看似简单的情况,这个问题很简洁。
The new Java 8 stream framework and friends make for some very concise java code, but I have come across a seemingly-simple situation that is tricky to do concisely.
考虑列表< Thing>东西
和方法可选<其他>解决(事情)
。我想将 Thing
映射到可选< Other>
s并获取第一个其他
。显而易见的解决方案是使用 things.stream()。flatMap(this :: resolve).findFirst()
,但 flatMap
要求您返回一个流,并且可选
没有 stream()
方法(或者是它是集合
或提供一种方法将其转换为或以集合
的形式查看。
Consider a List<Thing> things
and method Optional<Other> resolve(Thing thing)
. I want to map the Thing
s to Optional<Other>
s and get the first Other
. The obvious solution would be to use things.stream().flatMap(this::resolve).findFirst()
, but flatMap
requires that you return a stream, and Optional
doesn't have a stream()
method (or is it a Collection
or provide a method to convert it to or view it as a Collection
).
我能想到的最好的是:
things.stream()
.map(this::resolve)
.filter(Optional::isPresent)
.map(Optional::get)
.findFirst();
但这似乎是一个非常常见的案例。任何人都有更好的主意吗?
But that seems awfully long-winded for what seems like a very common case. Anyone have a better idea?
推荐答案
Java 9
已添加到JDK 9.这使您可以执行以下操作,而无需任何帮助方法:
Java 9
Optional.stream
has been added to JDK 9. This enables you to do the following, without the need of any helper method:
Optional<Other> result =
things.stream()
.map(this::resolve)
.flatMap(Optional::stream)
.findFirst();
Java 8
是的,这是API中的一个小洞,因为将Optional变为零或一个长度的流有点不方便。你可以这样做:
Java 8
Yes, this was a small hole in the API, in that it's somewhat inconvenient to turn an Optional into a zero-or-one length Stream. You could do this:
Optional<Other> result =
things.stream()
.map(this::resolve)
.flatMap(o -> o.isPresent() ? Stream.of(o.get()) : Stream.empty())
.findFirst();
在flatMap中使用三元运算符有点麻烦,所以写起来可能会更好一个小帮手功能:
Having the ternary operator inside the flatMap is a bit cumbersome, though, so it might be better to write a little helper function to do this:
/**
* Turns an Optional<T> into a Stream<T> of length zero or one depending upon
* whether a value is present.
*/
static <T> Stream<T> streamopt(Optional<T> opt) {
if (opt.isPresent())
return Stream.of(opt.get());
else
return Stream.empty();
}
Optional<Other> result =
things.stream()
.flatMap(t -> streamopt(resolve(t)))
.findFirst();
在这里,我已经内联调用resolve()而不是单独的map()操作,但这是一个品味问题。
Here, I've inlined the call to resolve() instead of having a separate map() operation, but this is a matter of taste.
这篇关于在Stream :: flatMap中使用Java 8的Optional的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!