在单个表达式中展开Guava可选项

时间:2012-12-08 01:16:48

标签: java guava

作为同时在GWT工作的Scala开发人员,我欢迎向Guava添加Optional

我们最常见的Optional用例之一是从方法返回可选值时(正如What's the point of Guava's Optional class的答案所示。

在scala中,我经常编写这样的代码:

def someExpensiveOperation(params: Type): Option[ResultType] = ...
someExpensiveOperation(params).foreach({ val =>
  doSomethingWithVal (val)
})

Guava的选项似乎不允许比这样的东西更优雅:

Optional<MyType> optionalResponse = someExpensiveOperation(params);
if (optionalResponse.isPresent()) {
    doSomethingWithVal(optionalResponse.get())
}

局部变量是多余的,它需要重复一个可以抽象的模式(if (optional.isPresent()) { doSomethingWith(optional.get()) })。

另一种选择是调用两次返回Optional的方法:

if (someExpensiveOperation(params).isPresent()) {
    doSomethingWithVal(someExpensiveOperation(params).get())
}

但这显然是不可取的,因为它不必要地多次调用昂贵的操作。

我很好奇其他人如何处理这个非常常见的情况(可能是通过编写像<T>useIfPresent(Optional<T> val, Closure<? super T> closure)这样的静态实用工具?)或者是否有人找到了更优雅的解决方案。

此外,如果有人知道为什么省略了Optional.foreach(Closure<? super T> closure)(但希望更好的名字)这样的方法,我很想知道这个理由。

1 个答案:

答案 0 :(得分:7)

它不在那里,因为我们觉得写一个Closure的匿名类尴尬更尴尬和更不易读 - 至少在Java中,不一定在Scala中 - 比你已经编写的局部变量和if语句

那说,另一种选择是

for (Foo x : someExpensiveOperation().asSet()) {
  // do stuff with x
}

请注意,此处需要asSet - Optional非常故意不会实施Iterable