Je souhaite remplacer le code suivant à l'aide de Java8 Optional
:
public Obj getObjectFromDB() {
Obj obj = dao.find();
if (obj != null) {
obj.setAvailable(true);
} else {
logger.fatal("Object not available");
}
return obj;
}
Le pseudocode suivant ne fonctionne pas car il n'y a pas de méthode orElseRun
, mais il illustre de toute façon mon objectif:
public Optional<Obj> getObjectFromDB() {
Optional<Obj> obj = dao.find();
return obj.ifPresent(obj.setAvailable(true)).orElseRun(logger.fatal("Object not available"));
}
Avec Java 9 ou supérieur, ifPresentOrElse
est probablement ce que vous voulez:
Optional<> opt = dao.find();
opt.ifPresentOrElse(obj -> obj.setAvailable(true),
() -> logger.error("…"));
Currying en utilisant vavr ou similaire pourrait obtenir un code encore plus ordonné, mais je n'ai pas encore essayé.
Je ne pense pas que vous puissiez le faire en une seule déclaration. Mieux faire:
if (!obj.isPresent()) {
logger.fatal(...);
} else {
obj.get().setAvailable(true);
}
return obj;
Vous devrez diviser cela en plusieurs déclarations. Voici un moyen de le faire:
if (!obj.isPresent()) {
logger.fatal("Object not available");
}
obj.ifPresent(o -> o.setAvailable(true));
return obj;
Une autre façon (éventuellement trop élaborée) consiste à utiliser map
:
if (!obj.isPresent()) {
logger.fatal("Object not available");
}
return obj.map(o -> {o.setAvailable(true); return o;});
Si obj.setAvailable
renvoie commodément obj
, vous pouvez simplement utiliser le deuxième exemple pour:
if (!obj.isPresent()) {
logger.fatal("Object not available");
}
return obj.map(o -> o.setAvailable(true));
Pour Java 8 Spring propose ifPresentOrElse
dans "Méthodes utilitaires permettant de travailler avec Optionals" pour atteindre vos objectifs. Exemple serait:
import static org.springframework.data.util.Optionals.ifPresentOrElse;
ifPresentOrElse(dao.find(), obj -> obj.setAvailable(true), () -> logger.fatal("Object not available"));
Tout d’abord, votre dao.find()
devrait soit renvoyer un Optional<Obj>
ou vous devrez en créer un.
par exemple.
Optional<Obj> = dao.find();
ou vous pouvez le faire vous-même comme:
Optional<Obj> = Optional.ofNullable(dao.find());
celui-ci retournera Optional<Obj>
s'il est présent ou Optional.empty()
s'il n'est pas présent.
Alors maintenant passons à la 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;
});
}
C'est la doublure que vous recherchez :)
Là est une méthode .orElseRun
, mais elle s’appelle .orElseGet
, le problème est que, contrairement à .map
, .isPresent
ne renvoie pas un Optional<Obj>
.
Si vous voulez vraiment faire cela en une seule déclaration c'est 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();
});
}
Mais c’est encore plus difficile que ce que vous aviez auparavant.
J'ai pu proposer deux solutions "une ligne", par exemple:
obj.map(o -> (Runnable) () -> o.setAvailable(true))
.orElse(() -> logger.fatal("Object not available"))
.run();
ou
obj.map(o -> (Consumer<Object>) c -> o.setAvailable(true))
.orElse(o -> logger.fatal("Object not available"))
.accept(null);
ou
obj.map(o -> (Supplier<Object>) () -> {
o.setAvailable(true);
return null;
}).orElse(() () -> {
logger.fatal("Object not available")
return null;
}).get();
Cela n'a pas l'air bien, quelque chose comme orElseRun
serait beaucoup mieux, mais je pense que l'option avec Runnable est acceptable si vous voulez vraiment une solution en une seule ligne.
Vous avez besoin de Optional.isPresent () et orElse () . Votre extrait ne fonctionnera pas car il ne renverra rien s’il n’est pas présent.
Le point de option est de le renvoyer à partir de la méthode.