Ich habe diesen 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")));
das ist total gut, aber ich denke, es ist ein bisschen chaotisch und deckt nicht den ganzen null pointer exception
ab (siehe Kommentar).
Ich versuche, diesen Code in umzuwandeln
Coverage mainCoverage1 = illus.getLifes().stream()
.filter(Life::isIsmain)
.map(Life::getCoverages)
.filter(Coverage::isMainplan) //<== cannot filter from list coverage to one main coverage
...
Nachdem ich das Leben der Berichterstattung zugeordnet habe, scheint es keine Liste mehr zu sein. Die Frage ist also, wie ich den ersten Abschnitt in null safe umwandeln und vielleicht kürzen kann?
Life::getCoverages
gibt eine Sammlung zurück, daher funktioniert der Filter Coverage::isMainplan
nicht. Stattdessen sollten Sie flatMap
die nach .map(Life::getCoverages)
zurückgegebenen Sequenzen verwenden und dann die filter
-Operation auf Coverage
anwenden:
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(...);
Ich habe ein paar Dinge zu Ihrem Code hinzugefügt:
.filter(Objects::nonNull)
after .map(Life::getCoverages)
hinzugefügt, das Sie unkommentieren können, wenn die zurückgegebenen Elemente möglicherweise null sind..flatMap(Collection::stream)
hinzugefügt, das einen Stream zurückgibt, der aus den Ergebnissen des Ersetzens jedes Elements dieses Streams durch den Inhalt eines zugeordneten Streams besteht, der durch Anwenden der bereitgestellten Zuordnungsfunktion auf jedes Element erzeugt wird. .filter(Objects::nonNull)
hinzugefügt, das Sie auskommentieren können, wenn die nach flatMap
zurückgegebenen Elemente möglicherweise null sind..filter(Coverage::isMainplan)
anwenden können und schließlich das erste Objekt abrufen, das die Kriterien erfüllt, über findFirst
. Falls keines vorhanden ist, geben Sie einen Standardwert über orElse
an.Ich würde empfehlen, sich die folgenden Blogs anzusehen, um sich mit der flatMap
-Methode vertraut zu machen:
Fügen Sie in filter
eine Bedingung hinzu. Wenn die Liste nicht null ist und i.isIsmain
dann nur filtern, können Sie public static boolean isNull(Object obj)
oder public static boolean nonNull(Object obj)
verwenden
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")));
Im ersten Teil Ihres Codes können Sie eine filter(e -> e != null)
eingeben, um sich zu vergewissern, dass die List
null ist, um keine NPE zu werfen:
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"))
Das Problem mit Ihrem zweiten Code-Snippet ist, dass ich davon ausgehe, dass Life::getCoverages
eine Collection
zurückgibt, keine einzelnen Coverage
-Objekte. Daher können Sie Coverage::isMainplan
nicht aufrufen
Das Beispiel, das Sie gegeben haben, und die Antworten, die hier dafür gegeben wurden, brechen einige Prinzipien der sauberen funktionalen Stilcodierung.
Erstens sollten Sie Terminalaktionen nicht mischen und Streams in derselben Code-Kette/-Pipeline erneut erstellen. Wie in Ihrem Beispiel stream (). FindFirst (). OrElseThrow (..). Stream (). OtherActions. Es ist wirklich keine gute Übung und fehleranfällig. Im Idealfall sollte eine Kette von Java Stream-API-Aufrufen mit einem einzelnen Stream funktionieren. Auf diese Weise ist es einfacher, Ihren Code nachzuvollziehen und zu begründen.
Zweitens haben Sie erwähnt, dass dieses Bit den Nullzeiger exkl. Treffen könnte:
.getCoverages()
.stream() // <==may cause null here if list coverage is null
wenn getCoverages () eine Auflistung zurückgeben soll, sollte es niemals null zurückgeben, sondern immer eine leere Auflistung.
Teilen Sie Ihren Code in separate logische Teile und geben Sie ihm einige aussagekräftige Namen:
Coverage mainCoverage = illus.getLifes().stream()
.filter(Life::isIsmain)
.findFirst()
.orElseThrow(() -> new ServiceInvalidAgurmentGeneraliException(env.getProperty("MSG_002")));
Coverage mainplan = mainCoverage.getCoverages().stream()
.filter(Coverage::isMainplan)
.findFirst()
.orElseThrow(() -> new ServiceInvalidAgurmentGeneraliException(env.getProperty("MSG_002")));
Es sieht viel besser aus als Ihr Ausgangspunkt. Ich hoffe das hilft.
Sie können versuchen, den resultierenden Collection<Coverage>
in einen Optional<Collection<Coverage>>
zu kapseln, damit Sie in einer null safe - Weise kartieren können.
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);