Java 8 中的链式可选项
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/28514704/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Chaining Optionals in Java 8
提问by piler
Looking for a way to chain optionals so that the first one that is present is returned. If none are present Optional.empty()
should be returned.
寻找一种链接选项的方法,以便返回存在的第一个选项。如果不存在,Optional.empty()
则应返回。
Assuming I have several methods like this:
假设我有几种这样的方法:
Optional<String> find1()
I'm trying to chain them:
我试图链接它们:
Optional<String> result = find1().orElse( this::find2 ).orElse( this::find3 );
but of course that doesn't work because orElse
expects a value and orElseGet
expects a Supplier
.
但当然这不起作用,因为orElse
期望一个值并orElseGet
期望一个Supplier
.
采纳答案by Sauli T?hk?p??
Use a Stream:
使用流:
Stream.of(find1(), find2(), find3())
.filter(Optional::isPresent)
.map(Optional::get)
.findFirst();
If you need to evaluate the find methods lazily, use supplier functions:
如果您需要懒惰地评估 find 方法,请使用供应商函数:
Stream.of(this::find1, this::find2, this::find3)
.map(Supplier::get)
.filter(Optional::isPresent)
.map(Optional::get)
.findFirst();
回答by Alexis C.
You could do it like this:
你可以这样做:
Optional<String> resultOpt = Optional.of(find1()
.orElseGet(() -> find2()
.orElseGet(() -> find3()
.orElseThrow(() -> new WhatEverException()))));
Though I'm not sure it improves readability IMO. Guava provides a way to chain Optionals:
虽然我不确定它会提高 IMO 的可读性。Guava 提供了一种链接 Optionals 的方法:
import com.google.common.base.Optional;
Optional<String> resultOpt = s.find1().or(s.find2()).or(s.find3());
It could be another alternative for your problem but does not use the standard Optional class in the JDK.
它可能是您问题的另一种选择,但不使用 JDK 中的标准 Optional 类。
If you want to keep the standard API, you could write a simple utility method:
如果您想保留标准 API,您可以编写一个简单的实用程序方法:
static <T> Optional<T> or(Optional<T> first, Optional<T> second) {
return first.isPresent() ? first : second;
}
and then:
进而:
Optional<String> resultOpt = or(s.find1(), or(s.find2(), s.find3()));
If you have a lot of optionals to chains, maybe it's better to use the Stream approach as other mentionned already.
如果您有很多链的可选选项,也许最好使用 Stream 方法,就像其他人已经提到的那样。
回答by glglgl
Maybe one of
也许其中之一
public <T> Optional<? extends T> firstOf(Optional<? extends T> first, @SuppressWarnings("unchecked") Supplier<Optional<? extends T>>... supp) {
if (first.isPresent()) return first;
for (Supplier<Optional <? extends T>> sup : supp) {
Optional<? extends T> opt = sup.get();
if (opt.isPresent()) {
return opt;
}
}
return Optional.empty();
}
public <T> Optional<? extends T> firstOf(Optional<? extends T> first, Stream<Supplier<Optional<? extends T>>> supp) {
if (first.isPresent()) return first;
Stream<Optional<? extends T>> present = supp.map(Supplier::get).filter(Optional::isPresent);
return present.findFirst().orElseGet(Optional::empty);
}
will do.
会做。
The first one iterates over an array of suppliers. The first non-empty Optional<>
is returned. If we don't find one, we return an empty Optional
.
第一个迭代一系列供应商。Optional<>
返回第一个非空。如果我们没有找到,我们返回一个空的Optional
。
The second one does the same with a Stream
of Suppliers
which is traversed, each one asked (lazily) for their value, which is then filtered for empty Optional
s. The first non-empty one is returned, or if no such exists, an empty one.
第二个做同样的事情Stream
,Suppliers
其中 a 被遍历,每个人(懒惰地)询问它们的值,然后过滤空的Optional
s。返回第一个非空的,或者如果不存在,则返回一个空的。
回答by Indrek Ots
Inspired by Sauli's answer, it is possible to use the flatMap()
method.
受 Sauli 回答的启发,可以使用该flatMap()
方法。
Stream.of(this::find1, this::find2, this::find3)
.map(Supplier::get)
.flatMap(o -> o.map(Stream::of).orElseGet(Stream::empty))
.findFirst();
Converting an Optional into a Stream is cumbersome. Apparently, this is going to be fixed with JDK9. So this could be written as
将 Optional 转换为 Stream 很麻烦。显然,这将通过 JDK9 修复。所以这可以写成
Stream.of(this::find1, this::find2, this::find3)
.map(Supplier::get)
.flatMap(Optional::stream)
.findFirst();
Update after Java 9 was released
Java 9 发布后的更新
Although the original question was about Java 8, Optional::or
was introduced in Java 9. With it, the problem could be solved as follows
虽然原来的问题是关于Java 8的,Optional::or
是在Java 9中引入的。有了它,问题可以解决如下
Optional<String> result = find1()
.or(this::find2)
.or(this::find3);
回答by Adit chandel
To perform Optional ChainingFirst convertStream to OptionalUsing either of the two methods
要执行可选链首先使用两种方法之一将流转换为可选
- findAny() or findFirst()
- min() / max()
- findAny() 或 findFirst()
- 最小()/最大()
Once optional is obtained optional has two more instance method which are also present in Stream class i.e filter and map(). use these on methods and to check output use ifPresent(System.out :: Println)
一旦获得可选的可选有两个实例方法,它们也存在于 Stream 类中,即 filter 和 map()。在方法上使用这些并检查输出使用 ifPresent(System.out :: Println)
ex:
前任:
Stream s = Stream.of(1,2,3,4);
流 s = Stream.of(1,2,3,4);
s.findFirst().filter((a)->a+1).ifPresent(System.out :: Println)
s.findFirst().filter((a)->a+1).ifPresent(System.out :: Println)
Output is : 2
输出为:2