我正在根据用户srborlongan提出的编辑将第二个答案添加到我的其他答案中。我认为提出的技术很有趣,但它并不适合作为我的答案的编辑。其他人同意了,提议的编辑被否决了。(我不是选民之一。不过,这项技术有其优点。如果srborlongan发布他/她自己的答案,那将是最好的。这还没有发生,我不希望这项技术在StackOverflow拒绝的编辑历史的迷雾中丢失,所以我决定自己把它作为一个单独的答案出现。
基本上,该技术是以聪明的方式使用某些方法,以避免必须使用三元运算符()或if/else语句。Optional
? :
我的内联示例将以这种方式重写:
Optional<Other> result =
things.stream()
.map(this::resolve)
.flatMap(o -> o.map(Stream::of).orElseGet(Stream::empty))
.findFirst();
使用帮助器方法的我的示例将按以下方式重写:
/**
* 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) {
return opt.map(Stream::of)
.orElseGet(Stream::empty);
}
Optional<Other> result =
things.stream()
.flatMap(t -> streamopt(resolve(t)))
.findFirst();
评论
让我们直接比较原始版本与修改版本:
// original
.flatMap(o -> o.isPresent() ? Stream.of(o.get()) : Stream.empty())
// modified
.flatMap(o -> o.map(Stream::of).orElseGet(Stream::empty))
原始方法是一种直截了当的、如果熟练的方法:我们得到一个;如果它有一个值,我们返回一个包含该值的流,如果它没有值,我们返回一个空流。非常简单,易于解释。Optional<Other>
这种修改是聪明的,并且具有避免条件的优点。(我知道有些人不喜欢三元算子。如果误用,它确实会使代码难以理解。但是,有时事情可能太聪明了。修改后的代码也以 .然后它调用,其定义如下:Optional<Other>
Optional.map
如果存在值,则对其应用提供的映射函数,如果结果为非 null,则返回描述结果的 Optional。否则,返回空的 Optional。
该调用返回 .如果输入 Optional 中存在一个值,则返回的 Optional 将包含一个 Stream,其中包含单个 Other 结果。但是,如果该值不存在,则结果为空的 Optional。map(Stream::of)
Optional<Stream<Other>>
接下来,调用 将返回类型为 的值。如果其输入值存在,则获取该值,即单元素 。否则(如果输入值不存在),它将返回空 。因此,结果是正确的,与原始条件代码相同。orElseGet(Stream::empty)
Stream<Other>
Stream<Other>
Stream<Other>
在讨论我的答案的评论中,关于被拒绝的编辑,我将这种技术描述为“更简洁,但也更晦涩”。我支持这一点。我花了一段时间才弄清楚它在做什么,我也花了一段时间写下上面关于它在做什么的描述。关键的微妙之处在于从 到 的转换。一旦你摸索了这一点,这是有道理的,但对我来说并不明显。Optional<Other>
Optional<Stream<Other>>
不过,我要承认,随着时间的推移,最初晦涩难懂的东西可能会变成习语。这种技术可能最终成为实践中最好的方法,至少在被添加之前(如果它曾经这样做的话)。Optional.stream
更新:已添加到 JDK 9。Optional.stream