我正在尝试了解Java 8中ifPresent()
API的Optional
方法。
我的逻辑很简单:
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
支票。
有什么想法吗?
答案 0 :(得分:103)
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()
。
答案 1 :(得分:11)
除了@ 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
})
对我来说,这更直观。
答案 2 :(得分:4)
使用flatMap。如果存在值,则flatMap返回仅包含该值的顺序Stream,否则返回空Stream。因此无需使用ifPresent()
。例如:
list.stream().map(data -> data.getSomeValue).map(this::getOptinalValue).flatMap(Optional::stream).collect(Collectors.toList());
答案 3 :(得分:3)
您需要像这样使用它:
user.ifPresent(ClassNameWhereMethodIs::doSomethingWithUser);
方法ifPresent()
获取Consumer
对象作为参数和(来自JavaDoc):&#34;如果存在值,则使用值调用指定的使用者。&#34 ;将其变量user
赋值。
答案 4 :(得分:2)
为什么要编写简单的复杂代码?
实际上,如果您绝对要使用Optional
类,那么最简单的代码就是您已经编写的代码...
if (user.isPresent())
{
doSomethingWithUser(user.get());
}
此代码的优点是
仅仅因为Oracle在Java 8中添加了Optional
类并不意味着在所有情况下都必须使用该类。