Java 如果不存在,如何在 Optional 上执行逻辑?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/29235982/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to execute logic on Optional if not present?
提问by membersound
I want to replace the following code using java8 Optional
:
我想使用 java8 替换以下代码Optional
:
public Obj getObjectFromDB() {
Obj obj = dao.find();
if (obj != null) {
obj.setAvailable(true);
} else {
logger.fatal("Object not available");
}
return obj;
}
The following pseudocode does not work as there is no orElseRun
method, but anyways it illustrates my purpose:
以下伪代码不起作用,因为没有orElseRun
方法,但无论如何它说明了我的目的:
public Optional<Obj> getObjectFromDB() {
Optional<Obj> obj = dao.find();
return obj.ifPresent(obj.setAvailable(true)).orElseRun(logger.fatal("Object not available"));
}
采纳答案by Andreas
With Java 9 or higher, ifPresentOrElse
is most likely what you want:
使用 Java 9 或更高版本,ifPresentOrElse
很可能是您想要的:
Optional<> opt = dao.find();
opt.ifPresentOrElse(obj -> obj.setAvailable(true),
() -> logger.error("…"));
Currying using vavror alike might get even neater code, but I haven't tried yet.
回答by Konstantin Yovkov
I don't think you can do it in a single statement. Better do:
我不认为你可以在一个声明中做到这一点。最好这样做:
if (!obj.isPresent()) {
logger.fatal(...);
} else {
obj.get().setAvailable(true);
}
return obj;
回答by NimChimpsky
You need Optional.isPresent()and orElse(). Your snippet won;t work because it doesn't return anything if not present.
您需要Optional.isPresent()和orElse()。您的代码段将不起作用,因为如果不存在,它不会返回任何内容。
The point of Optional is to return it from the method.
Optional 的重点是从方法中返回它。
回答by Duncan Jones
You will have to split this into multiple statements. Here is one way to do that:
您必须将其拆分为多个语句。这是一种方法:
if (!obj.isPresent()) {
logger.fatal("Object not available");
}
obj.ifPresent(o -> o.setAvailable(true));
return obj;
Another way (possibly over-engineered) is to use map
:
另一种方法(可能过度设计)是使用map
:
if (!obj.isPresent()) {
logger.fatal("Object not available");
}
return obj.map(o -> {o.setAvailable(true); return o;});
If obj.setAvailable
conveniently returns obj
, then you can simply the second example to:
如果obj.setAvailable
方便地返回obj
,那么您可以简单地将第二个示例改为:
if (!obj.isPresent()) {
logger.fatal("Object not available");
}
return obj.map(o -> o.setAvailable(true));
回答by mike
I suppose you cannot change the dao.find()
method to return an instance of Optional<Obj>
, so you have to create the appropriate one yourself.
我想您无法更改dao.find()
方法以返回 的实例Optional<Obj>
,因此您必须自己创建合适的方法。
The following code should help you out. I've create the class OptionalAction
,
which provides the if-else mechanism for you.
下面的代码应该可以帮助你。我已经创建了 class OptionalAction
,它为您提供了 if-else 机制。
public class OptionalTest
{
public static Optional<DbObject> getObjectFromDb()
{
// doa.find()
DbObject v = find();
// create appropriate Optional
Optional<DbObject> object = Optional.ofNullable(v);
// @formatter:off
OptionalAction.
ifPresent(object)
.then(o -> o.setAvailable(true))
.elseDo(o -> System.out.println("Fatal! Object not available!"));
// @formatter:on
return object;
}
public static void main(String[] args)
{
Optional<DbObject> object = getObjectFromDb();
if (object.isPresent())
System.out.println(object.get());
else
System.out.println("There is no object!");
}
// find may return null
public static DbObject find()
{
return (Math.random() > 0.5) ? null : new DbObject();
}
static class DbObject
{
private boolean available = false;
public boolean isAvailable()
{
return available;
}
public void setAvailable(boolean available)
{
this.available = available;
}
@Override
public String toString()
{
return "DbObject [available=" + available + "]";
}
}
static class OptionalAction
{
public static <T> IfAction<T> ifPresent(Optional<T> optional)
{
return new IfAction<>(optional);
}
private static class IfAction<T>
{
private final Optional<T> optional;
public IfAction(Optional<T> optional)
{
this.optional = optional;
}
public ElseAction<T> then(Consumer<? super T> consumer)
{
if (optional.isPresent())
consumer.accept(optional.get());
return new ElseAction<>(optional);
}
}
private static class ElseAction<T>
{
private final Optional<T> optional;
public ElseAction(Optional<T> optional)
{
this.optional = optional;
}
public void elseDo(Consumer<? super T> consumer)
{
if (!optional.isPresent())
consumer.accept(null);
}
}
}
}
回答by erkfel
I was able to came up with a couple of "one line" solutions, for example:
我能够想出几个“单行”解决方案,例如:
obj.map(o -> (Runnable) () -> o.setAvailable(true))
.orElse(() -> logger.fatal("Object not available"))
.run();
or
或者
obj.map(o -> (Consumer<Object>) c -> o.setAvailable(true))
.orElse(o -> logger.fatal("Object not available"))
.accept(null);
or
或者
obj.map(o -> (Supplier<Object>) () -> {
o.setAvailable(true);
return null;
}).orElse(() () -> {
logger.fatal("Object not available")
return null;
}).get();
It doesn't look very nice, something like orElseRun
would be much better, but I think that option with Runnable is acceptable if you really want one line solution.
它看起来不太好,类似的东西orElseRun
会好得多,但我认为如果您真的想要单行解决方案,那么带有 Runnable 的选项是可以接受的。
回答by UTF_or_Death
There isan .orElseRun
method, but it is called .orElseGet
, the problem is that, unlike .map
, .isPresent
doesn't return an Optional<Obj>
.
这里是一个.orElseRun
方法,但它被称为.orElseGet
,问题是,不像.map
,.isPresent
不返回Optional<Obj>
。
If you really want to do this in one statement this is possible:
如果你真的想在一个语句中做到这一点,这是可能的:
public Obj getObjectFromDB() {
return dao.find()
.map( obj -> {
obj.setAvailable(true);
return Optional.of(obj);
})
.orElseGet( () -> {
logger.fatal("Object not available");
return Optional.empty();
});
}
But this is even clunkier than what you had before.
但这比你以前的更笨拙。
回答by Hasasn
First of all, your dao.find()
should either return an Optional<Obj>
or you will have to create one.
首先,您dao.find()
应该返回一个Optional<Obj>
或者您必须创建一个。
e.g.
例如
Optional<Obj> = dao.find();
or you can do it yourself like:
或者你可以自己做:
Optional<Obj> = Optional.ofNullable(dao.find());
this one will return Optional<Obj>
if present or Optional.empty()
if not present.
Optional<Obj>
如果存在或Optional.empty()
不存在,这个将返回。
So now let's get to the solution,
所以现在让我们进入解决方案,
public Obj getObjectFromDB() {
return Optional.ofNullable(dao.find()).flatMap(ob -> {
ob.setAvailable(true);
return Optional.of(ob);
}).orElseGet(() -> {
logger.fatal("Object not available");
return null;
});
}
This is the one liner you're looking for :)
这是您正在寻找的一种衬垫 :)
回答by Cmyker
For Java 8 Spring offers ifPresentOrElse
from "Utility methods to work with Optionals" to achieve what you want.
Example would be:
对于 Java 8,Spring 提供ifPresentOrElse
了“使用 Optionals 的实用程序方法”来实现您想要的。示例是:
import static org.springframework.data.util.Optionals.ifPresentOrElse;
ifPresentOrElse(dao.find(), obj -> obj.setAvailable(true), () -> logger.fatal("Object not available"));
回答by sergeidyga
With Java 8 Optional
it can be done with:
使用 Java 8,Optional
它可以完成:
Optional<Obj> obj = dao.find();
obj.map(obj.setAvailable(true)).orElseGet(() -> {
logger.fatal("Object not available");
return null;
});