【问题标题】:How to get the first non empty Optional<T> from a list of Optional<T> [duplicate]如何从 Optional<T> 列表中获取第一个非空 Optional<T> [重复]
【发布时间】:2015-06-17 01:41:40
【问题描述】:

我正在将一些代码移至 java8,尝试(有时强迫自己)使用流和 lambda,但我对它们还不满意。

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

Optional<Fail> validate1(BusinessObject bo)

其中 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()

它有效,它完成了工作,它不执行不必要的方法,它清晰易读(如果 Optional.orElse 被命名为 getOrElse,它会更清晰,但我无法做到)。我想知道的是,这是否是一种合理的方式来做我想做的事,这段代码是否会被认为是“好的风格”或“惯用的 java8”,或者我是否在滥用 Stream 或 Optional,或者遗漏了一些明显的东西。

返回第一个非空 Optional 或返回第一个空 Optional(如果它们都是空的)的想法看起来很笼统,足以认为有一种官方方法可以做到这一点,我脑后的某些东西正在大喊“Monads!”,但是我对 Haskell 的无知几乎是完美的,所以我不知道。

【问题讨论】:

  • 看起来相当合理的代码风格。
  • 如果我是你,我可能会使用Stream.of(validate1(bo), validate1(bo), validate1(bo)) 而不是使用供应商。
  • @Jatin 会立即调用所有验证方法。 OP 只想在需要时调用它们。
  • @Misha 哎呀。是的。一个非常有效的观点。
  • this answer;它与您的问题的代码基本相同,但更简洁,通过在.findFirst() 之前使用.map(Optional::get),您可以保存orElse 部分......

标签: lambda functional-programming java-8


【解决方案1】:

Optional 很像 Stream,其中包含 0 或 1 个元素。然而它没有实现Stream,也没有stream() 方法(就像集合一样)。

但是,将Optional&lt;T&gt; 转换为Stream&lt;T&gt; 并不难,这个函数可以做到:

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

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

Stream.of(validate1, validate2, validate3)
        .map(Supplier::get)
        .flatMap(asStream())
        .findFirst();

【讨论】:

  • Java 9 will have。尽管如此,.flatMap(asStream()) 或 Java 9 的 .flatMap(Optional::stream).filter(Optional::isPresent).map(Optional::get) 并没有什么不同。它没有回答 OP 关于概念有效性的问题……
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-04
  • 2021-08-26
  • 2016-02-29
  • 1970-01-01
  • 1970-01-01
  • 2021-08-10
相关资源
最近更新 更多