web-dev-qa-db-ja.com

存在しない場合、オプションでロジックを実行する方法は?

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"));
}
62
membersound

Java 9以上では、 ifPresentOrElse がおそらく必要なものです。

Optional<> opt = dao.find();

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

vavr などを使用してカリー化すると、すっきりしたコードになることもありますが、まだ試していません。

91
Andreas

単一のステートメントでそれを行うことができるとは思わない。より良い:

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

これを複数のステートメントに分割する必要があります。これを行う1つの方法を次に示します。

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を返す場合、2番目の例を単純に使用して次のことができます。

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

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

Java 8の場合、Springは ifPresentOrElse から「オプションで動作するユーティリティメソッド」を使用して、目的を達成します。例は次のとおりです。

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

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

まず、dao.find()Optional<Obj>を返すか、作成する必要があります。

例えば.

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;
        });
    }

これはあなたが探している唯一のライナーです:)

9
Hasasn

is.orElseRunメソッドですが、.orElseGetと呼ばれますが、問題は、.mapとは異なり、.isPresentOptional<Obj>を返さないことです。

本当に1つのステートメントでこれを実行したい場合、これは可能です。

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

しかし、これは以前よりも不格好です。

5
UTF_or_Death

たとえば、次の2つの「1行」ソリューションを思いつくことができました。

    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のようなものの方がはるかに優れていますが、1行のソリューションが本当に必要な場合は、Runnableのオプションは受け入れられると思います。

1
erkfel

Optional.isPresent() および orElse() が必要です。スニペットは、存在しない場合は何も返さないため機能しません。

Optionalのポイントは、メソッドから返すことです。

0
NimChimpsky