如果不存在,如何在Optional上执行逻辑?

mem*_*und 65 java optional java-8

我想用java8替换下面的代码Optional:

public Obj getObjectFromDB() {
    Obj obj = dao.find();
    if (obj != null) {
        obj.setAvailable(true);
    } else {
        logger.fatal("Object not available");
    }

    return obj;
}
Run Code Online (Sandbox Code Playgroud)

以下伪代码不起作用,因为没有orElseRun方法,但无论如何它说明了我的目的:

public Optional<Obj> getObjectFromDB() {
    Optional<Obj> obj = dao.find();
    return obj.ifPresent(obj.setAvailable(true)).orElseRun(logger.fatal("Object not available"));
}
Run Code Online (Sandbox Code Playgroud)

And*_*eas 97

使用Java 9或更高版本,ifPresentOrElse很可能是您想要的:

Optional<> opt = dao.find();

opt.ifPresentOrElse(obj -> obj.setAvailable(true),
                    () -> logger.error("…"));
Run Code Online (Sandbox Code Playgroud)

使用vavr或类似的使用可能会得到更整洁的代码,但我还没有尝试过.

  • 看起来应该包含在v1(Java 8)... _好...... (43认同)
  • 是的......我也认为他们实际上错过了Java 8.更多......如果你想在价值存在的时候做点什么,他们给了"ifPresent()".如果你想在值存在时做某事,而在不存在时做其他事情,他们给出"ifPresentOrElse(f1,f2)".但是如果我只想做一些不存在的事情(例如"ifNotPresent()"之类的东西是合适的话)它仍然缺乏.使用ifPresentOrElse,我被迫使用一个在后一种情况下什么都不做的函数. (2认同)

Kon*_*kov 34

我认为你不能在一个声明中做到这一点.更好:

if (!obj.isPresent()) {
    logger.fatal(...);   
} else {
    obj.get().setAvailable(true);
}
return obj;
Run Code Online (Sandbox Code Playgroud)

  • 这可能是正确的答案,但这种优于"null"检查的方式是什么?从我的观点来看,如果没有"orElse ......",情况会更糟. (31认同)
  • @DaRich,你可以忘记代码中间的null,导致NPE的结果.但你不能忽视一个"可选",它始终是一个明确的(和危险的)决定. (3认同)

Dun*_*nes 10

您必须将其拆分为多个语句.这是一种方法:

if (!obj.isPresent()) {
  logger.fatal("Object not available");
}

obj.ifPresent(o -> o.setAvailable(true));
return obj;
Run Code Online (Sandbox Code Playgroud)

另一种方式(可能是过度设计)是使用map:

if (!obj.isPresent()) {
  logger.fatal("Object not available");
}

return obj.map(o -> {o.setAvailable(true); return o;});
Run Code Online (Sandbox Code Playgroud)

如果obj.setAvailable方便返回obj,那么您可以简单地将第二个示例:

if (!obj.isPresent()) {
  logger.fatal("Object not available");
}

return obj.map(o -> o.setAvailable(true));
Run Code Online (Sandbox Code Playgroud)


Has*_*asn 9

首先,您dao.find()应该返回一个Optional<Obj>或者您必须创建一个.

例如

Optional<Obj> = dao.find();
Run Code Online (Sandbox Code Playgroud)

或者你可以自己做,如:

Optional<Obj> = Optional.ofNullable(dao.find());
Run Code Online (Sandbox Code Playgroud)

Optional<Obj>如果存在或Optional.empty()不存在,这个将返回.

那么现在让我们来解决,

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;
        });
    }
Run Code Online (Sandbox Code Playgroud)

这是你正在寻找的一个班轮:)

  • 返回null会失败Optionals的目的.在OPs问题中,如果找不到对象,必须做什么是不明确的.恕我直言,它最好返回一个新实例化的对象,也许setAvailable为false.当然,这里OP已经致命,这意味着他可能打算终止所以它并不重要. (9认同)

Cmy*_*ker 9

对于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"));
Run Code Online (Sandbox Code Playgroud)


UTF*_*ath 6

这里一个.orElseRun方法,但它被称为.orElseGet,问题是,不像.map.isPresent不返回Optional<Obj>

如果您真的想在一条语句中执行此操作,则可以这样做:

public Obj getObjectFromDB() {
    return dao.find()
        .map( obj -> { 
            obj.setAvailable(true);
            return Optional.of(obj); 
         })
        .orElseGet( () -> {
            logger.fatal("Object not available"); 
            return Optional.empty();
    });
}
Run Code Online (Sandbox Code Playgroud)

但这比以前更笨拙。


Ste*_*aul 5

对于那些只想在不存在可选项的情况下执行副作用的人

即相当于ifAbsent()ifNotPresent()这里是对已经提供的伟大答案的轻微修改。

myOptional.ifPresentOrElse(x -> {}, () -> {
  // logic goes here
})
Run Code Online (Sandbox Code Playgroud)

  • ifPresentOrElse 需要 Java 9。 (2认同)

Mar*_* An 5

标题:“如果可选的不存在,如何执行逻辑?”

回答:

用作orElseGet()缺失的解决方法ifNotPresent()。因为它希望我们返回一些东西,所以就 return null

Optional.empty().orElseGet(() -> {
    System.out.println("The object is not present");
    return null;
});

//output: The object is not present

Run Code Online (Sandbox Code Playgroud)

或者


Optional.ofNullable(null).orElseGet(() -> {
    System.out.println("The object is not present");
    return null;
});

//output: The object is not present

Run Code Online (Sandbox Code Playgroud)

我还使用它来轻松实现具有延迟初始化的单例模式

public class Settings {
    private Settings(){}    
    private static Settings instance;
    public static synchronized Settings getInstance(){
        Optional.ofNullable(instance).orElseGet(() -> instance = new Settings());
        return instance;
    } 
}
Run Code Online (Sandbox Code Playgroud)

当然,getInstance()内容可以写成一行,直接返回第一条语句,但我想演示orElseGet()as的用法ifNotPresent()