簡體   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