如何从Optional <T>列表中获取第一个非空Optional <T>

Pab*_*afi 6 lambda functional-programming java-8

我正在将一些代码移动到java8,尝试(有时强迫自己)使用stream和lambdas,我对它们感到不舒服.

我在类中有一些验证业务对象的方法.每个方法看起来都像

Optional<Fail> validate1(BusinessObject bo)
Run Code Online (Sandbox Code Playgroud)

其中Fail是以某种方式描述错误的枚举,如果没有错误,则该方法返回Optional.empty().我不需要收集所有错误,但返回第一个错误,而不执行以下验证.

我正在做的是

//first convert methods to suppliers
Supplier<Optional<Fail>> validate1= () -> validate1(bo);
Supplier<Optional<Fail>> validate2= () -> validate2(bo);
Supplier<Optional<Fail>> validate3= () -> validate3(bo);
//then some stream magic
return Stream.of(validate1, validate2, validate3)
    .map(Supplier::get)
    .filter(f -> f.isPresent())
    .findFirst()
    .orElse(Optional.empty()); //without the orElse, no error would return
                                         // Optional(Optional.empty()) 
                                         // instead of Optional.empty()
Run Code Online (Sandbox Code Playgroud)

它工作,它完成工作,它不执行不必要的方法,它是清晰的(如果Optional.orElse被命名为getOrElse,它会更清晰,但这是我无法实现的).我想要找出的是,如果这是一个合理的方式来做我想要的,如果这个代码被认为是'好风格'或'惯用java8',或者我误用Stream或Optional,或者遗漏了一些明显的东西.

如果它们都是空的,那么返回第一个非空的Optional或者一个空的Optional的想法看起来很普遍,以为有一个正式的方法可以做到这一点,在我脑后的东西是大喊"Monads!",但我的无知Haskell几乎是完美的,所以我不知道.

bow*_*ore 3

Optional很像Stream里面有 0 或 1 个元素的 a 。然而它没有实现Stream,也没有stream()方法(就像集合一样)。

Optional<T>然而,将 an 转换为 a并不难Stream<T>,这个 Function 可以做到这一点:

public static <T> Function<Optional<? extends T>, Stream<T>> asStream() {
    return op -> op.map(Stream::of).orElseGet(Stream::empty);
}
Run Code Online (Sandbox Code Playgroud)

使用该方法,您可以简单地使用 flatMap :

Stream.of(validate1, validate2, validate3)
        .map(Supplier::get)
        .flatMap(asStream())
        .findFirst();
Run Code Online (Sandbox Code Playgroud)

  • Java 9 [将会有](http://download.java.net/jdk9/docs/api/java/util/Optional.html#stream--)。尽管如此,`.flatMap(asStream())` 或 Java 9 的 `.flatMap(Optional::stream)` 与 `.filter(Optional::isPresent).map(Optional::get)` 并没有什么不同。它并没有回答OP关于该概念总体有效性的问题...... (2认同)