Lez*_*rte 5 java optional java-8
假设我有一个函数Object f(String a, String b),我想调用两个不同的函数,这些函数返回Optional Strings以获取f Optional<String> getA()和的参数Optional<String> getB()。我可以想到两个解决方案,但是看起来都不是很干净,尤其是当您有更多参数时:
1:
return getA().flatMap(
a -> getB().map(
b -> f(a,b)).get()
Run Code Online (Sandbox Code Playgroud)
2:
Optional<String> a = getA();
Optional<String> b = getB();
if(a.isPresent() && b.isPresent()) {
return f(a.get(), b.get());
}
Run Code Online (Sandbox Code Playgroud)
有没有更清洁的方法可以做到这一点?
您刚刚偶然发现了函数式编程中称为提升的概念,它使您能够将常规函数(例如)提升A -> B到新的领域(例如Optional<A> -> Optional<B>)。
还有一个用于 flatMapping 和映射的语法糖,在 Haskell 和类似语言中更方便地称为do 表示法,在 Scala 中也用于理解。它为您提供了一种保持流程线性并避免嵌套的方法(在示例 1 中您被迫经历嵌套)。
不幸的是,Java 没有这样的东西,因为它的函数式编程能力很差,甚至Optional不是真正的一等公民(没有标准 API 实际使用它)。所以你只能坚持使用已经发现的方法。
如果您对上述概念感到好奇,请继续阅读。
起重
假设你有:
public String f(A a, B b) {
return b + "-" + a;
}
Run Code Online (Sandbox Code Playgroud)
与其 Scala 等效:
def f(a: A, b: B) = b + "-" + a
Run Code Online (Sandbox Code Playgroud)
提升f到Option(与 Java 中相同Optional)看起来像这样(使用 Scalaz 库,请参阅此处的 Cats)
val lifted = Monad[Option].lift2(f)
Run Code Online (Sandbox Code Playgroud)
lifted现在是一个等价于的函数:
public Optional<String> f(Optional<A> a, Optional<B> b) {
if(a.isPresent() && b.isPresent()) {
return Optional.of(b + "-" + a);
}
return Optional.empty;
}
Run Code Online (Sandbox Code Playgroud)
正是您正在寻找的内容,在 1 行中,并且适用于任何上下文(例如List,不仅仅是Option)和任何函数。
用于理解/Do 表示法
用于理解,你的例子看起来像这样(我认为,我的 Scala 很弱):
for {
a <- getA();
b <- getB();
} yield f(a, b)
Run Code Online (Sandbox Code Playgroud)
再说一次,这适用于任何可以进行平面映射的东西,比如List等等Future。