Domanda Come eseguire la logica su Opzionale se non presente?


Voglio sostituire il seguente codice usando java8 Optional:

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

    return obj;
}

Il seguente pseudocodice non funziona in quanto non esiste orElseRun metodo, ma comunque illustra il mio scopo:

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

44
2018-03-24 15:01


origine


risposte:


Non penso che tu possa farlo in una singola dichiarazione. Meglio fare:

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

26
2018-03-24 15:09



Java 9's nuovo ifPresentOrElse è molto probabilmente quello che vuoi:

Optional<> opt = dao.find();

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

Currying utilizzando vavr o allo stesso modo potrebbe ottenere codice ancora più ordinato, ma non ho ancora provato.


58
2017-10-10 12:28



Dovrai dividerlo in più affermazioni. Ecco un modo per farlo:

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

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

Un altro modo (possibilmente sovra-ingegnerizzato) è quello di usare map:

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

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

Se obj.setAvailable ritorna convenientemente obj, quindi puoi semplicemente il secondo esempio per:

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

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

7
2018-03-24 15:15



Prima di tutto, il tuo dao.find() dovrebbe o restituire un Optional<Obj> o dovrai crearne uno.

per esempio.

Optional<Obj> = dao.find();

oppure puoi farlo da solo come:

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

questo tornerà Optional<Obj> se presente o Optional.empty() se non presente.

Quindi ora arriviamo alla soluzione,

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

Questa è l'unica fodera che stai cercando :)


6
2018-04-27 09:03



è un .orElseRun metodo, ma è chiamato .orElseGet, il problema è che, a differenza di .map, .isPresent non restituisce un Optional<Obj>.

Se vuoi davvero farlo in una dichiarazione, questo è possibile:

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

Ma questo è ancora più clunkier di quello che avevi prima.


3
2018-04-17 19:19



Hai bisogno Optional.isPresent () e o altro(). Il tuo snippet ha vinto; t funziona perché non restituisce nulla se non presente.

Il punto di Optional è quello di restituirlo dal metodo.


0
2018-03-24 15:09



Sono stato in grado di trovare un paio di soluzioni "a una linea", ad esempio:

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

o

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

o

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

Non sembra molto carino, qualcosa di simile orElseRun sarebbe molto meglio, ma penso che l'opzione con Runnable sia accettabile se si vuole veramente una soluzione di linea.


0
2017-12-03 23:54