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

时间:2015-03-24 15:01:34

标签: java java-8 optional

我想使用java8 Optional替换以下代码:

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

    return obj;
}

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

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

13 个答案:

答案 0 :(得分:86)

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

Optional<> opt = dao.find();

opt.ifPresentOrElse(obj -> obj.setAvailable(true),
                    () -> logger.error("…"));

使用vavr或类似的方式进行调整可能会得到更整洁的代码,但我还没有尝试过。

答案 1 :(得分:33)

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

if (!obj.isPresent()) {
    logger.fatal(...);   
} else {
    obj.get().setAvailable(true);
}
return obj;

答案 2 :(得分:10)

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

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

obj.ifPresent(o -> o.setAvailable(true));
return obj;

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

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

return obj.map(o -> {o.setAvailable(true); return o;});

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

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

return obj.map(o -> o.setAvailable(true));

答案 3 :(得分:9)

首先,您的dao.find()应该返回Optional<Obj>,否则您必须创建一个。{/ p>

e.g。

Optional<Obj> = dao.find();

或者你可以自己做:

Optional<Obj> = Optional.ofNullable(dao.find());

如果存在,则会返回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;
        });
    }

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

答案 4 :(得分:5)

对于Java 8,Spring提供了“实用程序与Optionals一起使用”中的ifPresentOrElse,以实现所需的功能。 例如:

import static org.springframework.data.util.Optionals.ifPresentOrElse;    

ifPresentOrElse(dao.find(), obj -> obj.setAvailable(true), () -> logger.fatal("Object not available"));

答案 5 :(得分:4)

.orElseRun方法,但它被称为.orElseGet,问题在于,与.map不同,.isPresent没有&#39} ; t返回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();
    });
}

但这比你以前更笨拙。

答案 6 :(得分:1)

对于那些想要执行副作用的人仅当缺少可选选项时

即相当于ifAbsent()ifNotPresent()的地方,是对已经提供的重要答案的略微修改。

myOptional.ifPresentOrElse(x -> {}, () -> {
  // logic goes here
})

答案 7 :(得分:0)

您需要Optional.isPresent()orElse()。你的片段胜利了;因为它不会返回任何东西,如果不存在的话。

可选点是从方法中返回它。

答案 8 :(得分:0)

我能够想出几条&#34;一条线&#34;解决方案,例如:

    obj.map(o -> (Runnable) () -> o.setAvailable(true))
       .orElse(() -> logger.fatal("Object not available"))
       .run();

    obj.map(o -> (Consumer<Object>) c -> o.setAvailable(true))
       .orElse(o -> logger.fatal("Object not available"))
       .accept(null);

    obj.map(o -> (Supplier<Object>) () -> {
            o.setAvailable(true);
            return null;
    }).orElse(() () -> {
            logger.fatal("Object not available")
            return null;
    }).get();

它看起来不太好,像orElseRun这样的东西会好得多,但我认为如果你真的想要一个行解决方案,那么Runnable的选项是可以接受的。

答案 9 :(得分:0)

使用Java 8 Optional可以通过以下方式完成:

    Optional<Obj> obj = dao.find();

    obj.map(obj.setAvailable(true)).orElseGet(() -> {
        logger.fatal("Object not available");
        return null;
    });

答案 10 :(得分:0)

ifPresentOrElse 也可以处理空指针的情况。简单的方法。

   Optional.ofNullable(null)
            .ifPresentOrElse(name -> System.out.println("my name is "+ name),
                    ()->System.out.println("no name or was a null pointer"));

答案 11 :(得分:0)

标题:“如果不存在,如何在 Optional 上执行逻辑?”

答案:

使用 orElseGet() 作为缺少 ifNotPresent() 的解决方法。既然它希望我们返回一些东西就返回 null

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

//output: The object is not present


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

//output: The object is not present

我还使用它通过延迟初始化轻松实现 singleton pattern

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

答案 12 :(得分:-2)

我想您无法更改dao.find()方法以返回Optional<Obj>的实例,因此您必须自己创建适当的实例。

以下代码可以帮助您解决问题。我创建了类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);
      }
    }
  }
}