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

Yon*_*ree 6 java guava

作为一名也参与其中的Scala开发人员GWT,我欢迎加入OptionalGuava.

我们最常见的用例之一Optional是从方法中返回可选值(如Guava的Optional类的答案所示).

在scala中,我经常编写如下代码:

def someExpensiveOperation(params: Type): Option[ResultType] = ...
someExpensiveOperation(params).foreach({ val =>
  doSomethingWithVal (val)
})
Run Code Online (Sandbox Code Playgroud)

番石榴的选择似乎不允许比这样的东西更优雅:

Optional<MyType> optionalResponse = someExpensiveOperation(params);
if (optionalResponse.isPresent()) {
    doSomethingWithVal(optionalResponse.get())
}
Run Code Online (Sandbox Code Playgroud)

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

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

if (someExpensiveOperation(params).isPresent()) {
    doSomethingWithVal(someExpensiveOperation(params).get())
}
Run Code Online (Sandbox Code Playgroud)

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

我很好奇其他人是如何处理这种非常常见的情况的(也许是通过写一个静态的实用方法,比如<T>useIfPresent(Optional<T> val, Closure<? super T> closure)?)或者是否有人找到了更优雅的解决方案.

此外,如果有人知道为什么一个方法Optional.foreach(Closure<? super T> closure)(但希望更好的名字)被省略,我会很好奇听到理由.

Lou*_*man 7

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

也就是说,另一种选择是

for (Foo x : someExpensiveOperation().asSet()) {
  // do stuff with x
}
Run Code Online (Sandbox Code Playgroud)

请注意,asSet这里是必要的 - Optional非常故意不会实现Iterable.

  • 有点旧,但我想知道为什么`Optional.asSet()`返回`Set`而不是`ImmutableSet`,因为它被记录为返回不可变的.是因为`Optional`是在`cgcbase`中提供而不是在`cgccollect`中提供的? (2认同)