繁体   English   中英

Java 8将多个可选参数映射到函数中

[英]Java 8 Mapping multiple optional parameters into a function

假设我有函数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()

2:

Optional<String> a = getA();
Optional<String> b = getB();
if(a.isPresent() && b.isPresent()) {
    return f(a.get(), b.get());
}

有更清洁的方法吗?

您可以流式传输参数并仅应用条件一次,但是这是否比您的解决方案更优雅在旁观者眼中:

if (Stream.of(a, b).allMatch(Optional::isPresent)) {
    return f(a.get(), b.get());
}

您刚刚偶然发现了一个名为提升函数式编程的概念,它使您能够常规函数(例如A -> B提升到新域(例如Optional<A> -> Optional<B> )。

还有一个用于flatMapping的语法糖和更舒适的映射,称为Haskell和类似语言中的符号 ,以及Scala中的理解 它为您提供了一种保持流线性并避免嵌套的方法(您在示例1中被迫通过)。

遗憾的是,Java没有任何类型,因为它的函数式编程功能微不足道,甚至Optional也不是真正的一等公民(没有标准API实际使用它)。 所以你坚持使用你已经发现的方法。

如果您对上述概念感到好奇,请继续阅读。

吊装

假设你有:

public String f(A a, B b) {
    return b + "-" + a;
}

使用Scala等效:

def f(a: A, b: B) = b + "-" + a

f提升为Option (与Java中的Optional相同)将如下所示(使用Scalaz库):

val lifted = Monad[Option].lift2(f)

lifted现在的功能相当于:

public Optional<String> f(Optional<A> a, Optional<B> b) {
    if(a.isPresent() && b.isPresent()) {
        return Optional.of(b + "-" + a);
    }
    return  Optional.empty;
}

正是您正在寻找的,在一行,并适用于任何上下文(例如List ,而不仅仅是Option )和任何功能。

为了理解/做符号

用于理解 ,你的例子看起来像这样(我 ,我的Scala很弱):

for { 
    a <- getA();
    b <- getB();
} yield f(a, b)

而且,这适用于任何可以平面映射的内容,如ListFuture等。

我认为如果没有好的方法可以使用Optional ,那么无论如何都没有理由尝试使用它。

我觉得这比你的选择2更清洁,更简单:

String a = getA().orElse(null);
String b = getB().orElse(null);
if(a != null && b != null) {
    return f(a, b);
}

如果您确定a和b都存在(因为您最终要求get解决方案1似乎建议),我认为这非常简单:

    return f(getA().orElseThrow(() -> new NoSuchElementException("a not present")),
             getB().orElseThrow(() -> new NoSuchElementException("b not present")));

如果你不知道这两个都存在,我会1.它利用更喜欢你的解决方案Optional最好的。 只有我不会在最后调用get ,而是在你的情况下orElse或者是有意义的,例如:

    return getA()
            .flatMap(a -> getB().map(b -> f(a,b)))
            .orElse("Not both present");

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM