在Java 8中展开多个可选变量

时间:2016-04-06 10:50:30

标签: java scala optional

我有以下问题。我们假设您有2个Optional变量

Optional<Contact> c1 = ...
Optional<Contact> c2 = ...

以及需要2个类型Contact

变量的方法
void match(Contact c1, Contact c2) {...}

并且您需要打开c1和c2 Optional vars并将它们传递到match()方法。

我的问题是&#34;在Java 8中这是最优雅的方法吗?&#34;

到目前为止,我找到了两种方法:

  1. 使用isPresent

    if (c1.isPresent() && c2.isPresent()) {
        match(c1.get(), c2.get());
    }
    
  2. 使用嵌套的ifPresent

    c1.ifPresent((Contact _c1) -> {
        c2.ifPresent((Contact _c2) -> {
            match(_c1, _c2);
        });
    });
    
  3. 在我看来,这两种方式都很糟糕。在Scala我可以这样做:

    for {
        contact1 <- c1
        contact2 <- c2
    } yield {
        match(contact1, contact2);
    }
    

    Java 8中有没有比我上面描述的更简洁的方法呢?

3 个答案:

答案 0 :(得分:5)

scala中提供的解决方案只是内部使用flatMaps的语法糖。你也可以在Java 8中使用flatmaps(但它没有语法糖)。

c1.flatMap(contact1 -> c2.flatMap(contact2 -> match(contact1, contact2)));

它与您提供的解决方案2几乎相同。您还可以使用来自https://github.com/aol/cyclops-react(我是贡献者之一)或任何其他功能性java 8库的applicative functor。

Applicative functor

Optional<String> o3 = Maybe.fromOptional(o1).ap2(String::concat).ap(o2).toOptional();

有关-理解

Do.add(o1)
    .add(o2)
    .yield(a->b->a.concat(b));

答案 1 :(得分:5)

你可以通过以下函数来解释Scala for -reherehension to map / flatMap in Java 8:

public static <T,V> Optional<V> map2(Optional<T> opt1, Optional<T> opt2, BiFunction<T, T, V> f) {
    Optional<V> result = opt1.flatMap(t1 -> opt2.map(t2 -> f.apply(t1, t2)));
    return result;
}

然后传递你的函数 match

答案 2 :(得分:0)

如果您认为参数没有值作为例外,那么您可以像处理它们一样处理它们:

try {
    match(c1.orElseThrow(NoVal::new), c2.orElseThrow(NoVal::new));
} catch (NoVal ex) {
    ...
}

如果他们不是一个例外情况,那么我会选择你的第一个选项,因为他更清楚你的意图。在我看来,如果您希望在选项为空时切换到使用默认值,那么它非常清晰易读,并且很容易更改为使用orElse