J'ai ce morceau de code
Coverage mainCoverage = illus.getLifes().stream()
.filter(Life::isIsmain)
.findFirst()
.orElseThrow(() -> new ServiceInvalidAgurmentGeneraliException(env.getProperty("MSG_002")))
.getCoverages()
.stream() // <==may cause null here if list coverage is null
.filter(Coverage::isMainplan)
.findFirst()
.orElseThrow(() -> new ServiceInvalidAgurmentGeneraliException(env.getProperty("MSG_002")));
qui est totalement bon travail mais je pense que c'est un peu désordonné et ne couvre pas tout le null pointer exception
possible (voir le commentaire).
J'essaie de refactoriser ce code en
Coverage mainCoverage1 = illus.getLifes().stream()
.filter(Life::isIsmain)
.map(Life::getCoverages)
.filter(Coverage::isMainplan) //<== cannot filter from list coverage to one main coverage
...
Apparemment, après avoir associé la vie à la couverture, il ne s'agit plus d'une liste de couverture. La question est donc de savoir comment je peux refactoriser la première section en null safe et peut-être la raccourcir?
Life::getCoverages
retourne une collection; par conséquent, le filtre Coverage::isMainplan
ne fonctionnera pas. Vous devez plutôt flatMap
les séquences renvoyées après .map(Life::getCoverages)
, puis appliquer l'opération filter
à la Coverage
:
Coverage mainCoverage =
illus.getLifes()
.stream()
.filter(Life::isIsmain)
.map(Life::getCoverages)
//.filter(Objects::nonNull) uncomment if there can be null lists
.flatMap(Collection::stream) // <--- collapse the nested sequences
//.filter(Objects::nonNull) // uncomment if there can be null Coverage
.filter(Coverage::isMainplan)
.findFirst().orElse(...);
J'ai ajouté quelques éléments à votre code:
.filter(Objects::nonNull)
after .map(Life::getCoverages)
que vous pouvez supprimer, étant donné que les éléments renvoyés sont potentiellement nuls..flatMap(Collection::stream)
qui renvoie un flux contenant les résultats du remplacement de chaque élément de ce flux par le contenu d'un flux mappé produit en appliquant la fonction de mappage fournie à chaque élément. .filter(Objects::nonNull)
que vous pouvez supprimer, étant donné que les éléments retournés après flatMap
pourraient potentiellement être nuls..filter(Coverage::isMainplan)
et, enfin, récupérer le premier objet répondant aux critères via findFirst
et si aucun ne fournit alors une valeur par défaut via orElse
.Je vous suggère de consulter les blogs suivants pour vous familiariser avec la méthode flatMap
:
Ajouter une condition dans filter
si list n'est pas null et i.isIsmain
, alors seulement filtrer, vous pouvez utiliser public static boolean isNull(Object obj)
ou public static boolean nonNull(Object obj)
Coverage mainCoverage = illus.getLifes().stream()
.filter(i->i.isIsmain && Objects.nonNull(i.getCoverages()))
.findFirst()
.orElseThrow(() -> new ServiceInvalidAgurmentGeneraliException(env.getProperty("MSG_002")))
.getCoverages()
.stream() // <==may cause null here if list coverage is null
.filter(Coverage::isMainplan)
.findFirst()
.orElseThrow(() -> new ServiceInvalidAgurmentGeneraliException(env.getProperty("MSG_002")));
Dans la première partie de votre code, vous pouvez insérer une filter(e -> e != null)
pour savoir si la variable List
est nulle et ne lancera pas de NPE:
Coverage mainCoverage = illus.getLifes().stream()
.filter(Life::isIsmain)
.findFirst()
.orElseThrow(() -> new ServiceInvalidAgurmentGeneraliException(env.getProperty("MSG_002")))
.getCoverages()
.filter(e -> e != null) //<=== Filter out all null values
.stream()
.filter(Coverage::isMainplan)
.findFirst()
.orElseThrow(() -> new ServiceInvalidAgurmentGeneraliException(env.getProperty("MSG_002"))
Le problème avec votre deuxième extrait de code est que je suppose que Life::getCoverages
renvoie un objet Collection
, et non un objet Coverage
, vous ne pouvez donc pas appeler Coverage::isMainplan
dessus.
Vous pouvez essayer d'encapsuler le Collection<Coverage>
résultant dans un Optional<Collection<Coverage>>
afin de pouvoir effectuer un mappage de manière null safe.
final Supplier<ServiceInvalidAgurmentGeneraliException> customExceptionThrower = () -> new ServiceInvalidAgurmentGeneraliException(env.getProperty("MSG_002"));
final Collection<Coverage> firstMainLifeCoverages = illus.getLifes().stream()
.filter(Life::isIsmain)
.findFirst()
.orElseThrow(customExceptionThrower)
.getCoverages();
Optional.ofNullable(firstMainLifeCoverages)
.map(Collection::stream)
.orElseThrow(customExceptionThrower)
.filter(Coverage::isMainplan)
.findFirst()
.orElseThrow(customExceptionThrower);