pil*_*ler 59 java lambda optional java-8
寻找一种链接选项的方法,以便返回第一个存在的选项.如果没有,Optional.empty()则应退回.
假设我有几个像这样的方法:
Optional<String> find1()
Run Code Online (Sandbox Code Playgroud)
我想把它们链起来:
Optional<String> result = find1().orElse( this::find2 ).orElse( this::find3 );
Run Code Online (Sandbox Code Playgroud)
但当然这不起作用,因为orElse期望一个值,并orElseGet期望一个Supplier.
Sau*_*pää 80
使用流:
Stream.of(find1(), find2(), find3())
.filter(Optional::isPresent)
.map(Optional::get)
.findFirst();
Run Code Online (Sandbox Code Playgroud)
如果您需要懒惰地评估查找方法,请使用供应商功能:
Stream.of(this::find1, this::find2, this::find3)
.map(Supplier::get)
.filter(Optional::isPresent)
.map(Optional::get)
.findFirst();
Run Code Online (Sandbox Code Playgroud)
Ale*_* C. 33
你可以这样做:
Optional<String> resultOpt = Optional.of(find1()
.orElseGet(() -> find2()
.orElseGet(() -> find3()
.orElseThrow(() -> new WhatEverException()))));
Run Code Online (Sandbox Code Playgroud)
虽然我不确定它是否提高了IMO的可读性.Guava提供了一种链接Optionals的方法:
import com.google.common.base.Optional;
Optional<String> resultOpt = s.find1().or(s.find2()).or(s.find3());
Run Code Online (Sandbox Code Playgroud)
它可能是您的问题的另一种选择,但不使用JDK中的标准Optional类.
如果要保留标准API,可以编写一个简单的实用程序方法:
static <T> Optional<T> or(Optional<T> first, Optional<T> second) {
return first.isPresent() ? first : second;
}
Run Code Online (Sandbox Code Playgroud)
然后:
Optional<String> resultOpt = or(s.find1(), or(s.find2(), s.find3()));
Run Code Online (Sandbox Code Playgroud)
如果你有很多可选择的链,也许最好使用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();
Run Code Online (Sandbox Code Playgroud)
将Optional转换为Stream非常麻烦.显然,这将由JDK9修复.所以这可以写成
Stream.of(this::find1, this::find2, this::find3)
.map(Supplier::get)
.flatMap(Optional::stream)
.findFirst();
Run Code Online (Sandbox Code Playgroud)
Java 9发布后更新
尽管最初的问题是关于Java 8的,但是Optional::or在Java 9中引入了它.有了它,问题可以解决如下
Optional<String> result = find1()
.or(this::find2)
.or(this::find3);
Run Code Online (Sandbox Code Playgroud)
epo*_*pox 17
读者正在寻找的最有可能的情况(今天)
result = find1()
.or(this::find2)
.or(this::find3);
Run Code Online (Sandbox Code Playgroud)
result = Optional.ofNullable(find1()
.orElse(find2()
.orElse(find3()
.orElse(null))));
Run Code Online (Sandbox Code Playgroud)
性能:上述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.
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
30984 次 |
| 最近记录: |