正确使用 Optional.ifCurrent()

我试图理解 Java8中 OptionalAPI 的 ifPresent()方法。

我的逻辑很简单:

Optional<User> user=...
user.ifPresent(doSomethingWithUser(user.get()));

但这导致了一个编译错误:

ifPresent(java.util.functionError:(186, 74) java: 'void' type not allowed here)

我当然可以这样做:

if(user.isPresent())
{
doSomethingWithUser(user.get());
}

但这就像一个杂乱的 null检查。

如果我把代码改成这样:

 user.ifPresent(new Consumer<User>() {
@Override public void accept(User user) {
doSomethingWithUser(user.get());
}
});

代码越来越脏了,这让我想起了以前的 null检查。

有什么想法吗?

331761 次浏览

Optional<User>.ifPresent()接受一个 Consumer<? super User>作为参数。你传递给它一个类型为 void 的表达式。所以它不能编译。

一个 Consumer 将作为一个 lambda 表达式实现:

Optional<User> user = ...
user.ifPresent(theUser -> doSomethingWithUser(theUser));

或者更简单,使用方法引用:

Optional<User> user = ...
user.ifPresent(this::doSomethingWithUser);

这基本上和

Optional<User> user = ...
user.ifPresent(new Consumer<User>() {
@Override
public void accept(User theUser) {
doSomethingWithUser(theUser);
}
});

其思想是,只有当用户在场时,才会执行 doSomethingWithUser()方法调用。代码直接执行方法调用,并尝试将其 void 结果传递给 ifPresent()

您可以像下面这样使用方法引用:

user.ifPresent(ClassNameWhereMethodIs::doSomethingWithUser);

方法 ifPresent()获取 Consumer对象作为参数,并且(从 JavaDoc) : “如果存在一个值,则使用该值调用指定的使用者。”值是变量 user

或者,如果这个方法 doSomethingWithUserUser类中,而它不是 static,那么您可以像下面这样使用方法引用:

user.ifPresent(this::doSomethingWithUser);

除了@JBNizet 的回答之外,我对 ifPresent的一般用例是将 .isPresent().get()结合起来:

老办法:

Optional opt = getIntOptional();
if(opt.isPresent()) {
Integer value = opt.get();
// do something with value
}

新方法:

Optional opt = getIntOptional();
opt.ifPresent(value -> {
// do something with value
})

对我来说,这更直观。

使用平面地图。如果存在一个值,latMap 返回一个仅包含该值的连续 Stream,否则返回一个空 Stream。所以没有必要使用 ifPresent()。例如:

list.stream().map(data -> data.getSomeValue).map(this::getOptinalValue).flatMap(Optional::stream).collect(Collectors.toList());

既然可以简化代码,为什么还要编写复杂的代码呢?

实际上,如果您绝对要使用 Optional类,那么最简单的代码就是您已经编写的代码..。

if (user.isPresent())
{
doSomethingWithUser(user.get());
}

此代码的优点是

  1. 可读
  2. 易于调试(断点)
  3. 不难

仅仅因为 Oracle 在 Java8中添加了 Optional类,并不意味着这个类必须在所有情况下使用。