pil*_*ler 59 java lambda optional java-8
寻找一种链接选项的方法,以便返回第一个存在的选项.如果没有,Optional.empty()则应退回.
假设我有几个像这样的方法:
Optional<String> find1()
我想把它们链起来:
Optional<String> result = find1().orElse( this::find2 ).orElse( this::find3 );
但当然这不起作用,因为orElse期望一个值,并orElseGet期望一个Supplier.
Sau*_*pää 80
使用流:
Stream.of(find1(), find2(), find3())
    .filter(Optional::isPresent)
    .map(Optional::get)
    .findFirst();
如果您需要懒惰地评估查找方法,请使用供应商功能:
Stream.of(this::find1, this::find2, this::find3)
    .map(Supplier::get)
    .filter(Optional::isPresent)
    .map(Optional::get)
    .findFirst();
Ale*_* C. 33
你可以这样做:
Optional<String> resultOpt = Optional.of(find1()
                                .orElseGet(() -> find2()
                                .orElseGet(() -> find3()
                                .orElseThrow(() -> new WhatEverException()))));
虽然我不确定它是否提高了IMO的可读性.Guava提供了一种链接Optionals的方法:
import com.google.common.base.Optional;
Optional<String> resultOpt = s.find1().or(s.find2()).or(s.find3());
它可能是您的问题的另一种选择,但不使用JDK中的标准Optional类.
如果要保留标准API,可以编写一个简单的实用程序方法:
static <T> Optional<T> or(Optional<T> first, Optional<T> second) {
    return first.isPresent() ? first : second;
}
然后:
Optional<String> resultOpt = or(s.find1(), or(s.find2(), s.find3()));
如果你有很多可选择的链,也许最好使用Stream方法,就像其他提到的那样.
Ind*_*Ots 27
受Sauli的回答启发,可以使用该flatMap()方法.
Stream.of(this::find1, this::find2, this::find3)
  .map(Supplier::get)
  .flatMap(o -> o.map(Stream::of).orElseGet(Stream::empty))
  .findFirst();
将Optional转换为Stream非常麻烦.显然,这将由JDK9修复.所以这可以写成
Stream.of(this::find1, this::find2, this::find3)
  .map(Supplier::get)
  .flatMap(Optional::stream)
  .findFirst();
Java 9发布后更新
尽管最初的问题是关于Java 8的,但是Optional::or在Java 9中引入了它.有了它,问题可以解决如下
Optional<String> result = find1()
  .or(this::find2)
  .or(this::find3);
epo*_*pox 17
读者正在寻找的最有可能的情况(今天)
result = find1()
    .or(this::find2)
    .or(this::find3);
result = Optional.ofNullable(find1()
    .orElse(find2()
      .orElse(find3()
        .orElse(null))));
性能:上述Java 8解决方案每次都会预先调用find2()和find3() ,即使(稍后) find1()计算返回非空时也是如此。
更新:具有惰性求值的性能最佳Java 8解决方案(感谢 @Alexander 的评论)将是:
result = Optional.ofNullable(find1()
    .orElseGet(() -> find2()
      .orElseGet(() -> find3()
        .orElse(null))));      // <-- null would be the last resort, when all findN are empty.
                               //     #ofNullable (in the 1st line would wrap it to Optional
                               //     and return Optional.empty() as OP requires.