Hallo Java-Entwickler,
Ich weiß, dass das Thema ein bisschen sein kann, in advance
da das JDK8 noch nicht veröffentlicht ist (und vorerst sowieso nicht ..), aber ich habe einige Artikel über die Lambda-Ausdrücke und insbesondere den Teil gelesen, der sich auf die neue Sammlungs-API namens Stream bezieht.
Hier ist das Beispiel aus dem Artikel des Java-Magazins (es ist ein Otterpopulationsalgorithmus ..):
Set<Otter> otters = getOtters();
System.out.println(otters.stream()
.filter(o -> !o.isWild())
.map(o -> o.getKeeper())
.filter(k -> k.isFemale())
.into(new ArrayList<>())
.size());
Meine Frage ist, was passiert, wenn in der Mitte der internen Iteration von Set einer der Otter null ist?
Ich würde erwarten, dass eine NullPointerException ausgelöst wird, aber vielleicht stecke ich immer noch im vorherigen Entwicklungsparadigma (nicht funktionsfähig) fest. Kann mich jemand aufklären, wie damit umgegangen werden soll?
Wenn dies wirklich eine NullPointerException auslöst, finde ich die Funktion ziemlich gefährlich und muss nur wie folgt verwendet werden:
- Entwickler, um sicherzustellen, dass es keinen Nullwert gibt (möglicherweise mit einem vorherigen .filter (o -> o! = Null))
- Entwickler, um sicherzustellen, dass die Anwendung niemals einen Nullotter oder ein spezielles NullOtter-Objekt generiert, mit dem umgegangen werden soll.
Was ist die beste Option oder eine andere Option?
Vielen Dank!
quelle
filter(Objects::nonNull)
mitObjects
vonjava.utils
Antworten:
Gegenwärtiges Denken scheint darin zu bestehen, Nullen zu "tolerieren", dh sie im Allgemeinen zuzulassen, obwohl einige Operationen weniger tolerant sind und möglicherweise NPE auslösen. Weitere Informationen zu dieser Nachricht finden Sie in der Diskussion der Nullen auf der Mailingliste der Lambda Libraries-Expertengruppe . In der Folge ergab sich ein Konsens über Option 3 (mit einem bemerkenswerten Einwand von Doug Lea). Ja, die Besorgnis des OP über mit NPE explodierende Pipelines ist berechtigt.
Nicht umsonst bezeichnete Tony Hoare Nullen als "Milliarden-Dollar-Fehler". Der Umgang mit Nullen ist ein wahrer Schmerz. Selbst bei klassischen Sammlungen (ohne Berücksichtigung von Lambdas oder Streams) sind Nullen problematisch. Wie fge in einem Kommentar erwähnt, erlauben einige Sammlungen nulls und andere nicht. Bei Sammlungen, die Nullen zulassen, führt dies zu Mehrdeutigkeiten in der API. Bei Map.get () gibt eine Null-Rückgabe beispielsweise an, dass der Schlüssel vorhanden und sein Wert null ist oder dass der Schlüssel fehlt. Man muss zusätzliche Arbeit leisten, um diese Fälle zu disambiguieren.
Die übliche Verwendung für null ist das Fehlen eines Wertes. Der für Java SE 8 vorgeschlagene Ansatz besteht darin, einen neuen
java.util.Optional
Typ einzuführen , der das Vorhandensein / Fehlen eines Werts zusammen mit dem Verhalten der Angabe eines Standardwerts oder des Auslösens einer Ausnahme oder des Aufrufs einer Funktion usw. kapselt Der Wert fehlt.Optional
wird jedoch nur von neuen APIs verwendet, alles andere im System muss sich jedoch mit der Möglichkeit von Nullen abfinden.Mein Rat ist, tatsächliche Nullreferenzen so weit wie möglich zu vermeiden. Aus dem Beispiel ist schwer zu ersehen, wie es einen "Null" Otter geben könnte. Wenn dies jedoch erforderlich wäre, sind die Vorschläge des OP, Nullwerte herauszufiltern oder sie einem Sentinel-Objekt (dem Null-Objektmuster ) zuzuordnen, gute Ansätze.
quelle
null
ist, deshalb. Acc. Laut einer Umfrage, die ich gesehen habe (ich kann sie nicht finden), ist NPE die Ausnahme Nummer 1 in Java. SQL ist keine Programmiersprache auf hoher Ebene, sicherlich nicht funktionsfähig, was null verachtet, also ist es ihm egal.Obwohl die Antworten zu 100% korrekt sind, ein kleiner Vorschlag zur Verbesserung der
null
Fallbehandlung der Liste selbst mit Optional :Mit diesem Teil
Optional.ofNullable(listOfStuff).orElseGet(Collections::emptyList)
können Sie den Fall, wenn erlistOfStuff
null ist, gut behandeln und eine leere Liste zurückgeben, anstatt mit NullPointerException zu scheitern.quelle
Die Antwort von Stuart liefert eine gute Erklärung, aber ich möchte ein anderes Beispiel geben.
Ich bin auf dieses Problem gestoßen, als ich versucht habe, einen
reduce
Stream mit Nullwerten auszuführen (tatsächlich warLongStream.average()
dies eine Art von Reduzierung). Da durchschnitt () zurückgibtOptionalDouble
, habe ich angenommen, dass der Stream Nullen enthalten könnte, aber stattdessen wurde eine NullPointerException ausgelöst. Dies liegt an Stuarts Erklärung von null gegen leer.Also, wie das OP vorschlägt, habe ich einen Filter wie folgt hinzugefügt:
Oder verwenden Sie, wie unten angegeben, das von der Java-API bereitgestellte Prädikat:
Aus der Mailinglistendiskussion hat Stuart verlinkt: Brian Goetz über Nullen in Streams
quelle
Wenn Sie nur Nullwerte aus einem Stream herausfiltern möchten, können Sie einfach einen Methodenverweis auf java.util.Objects.nonNull (Object) verwenden . Aus seiner Dokumentation:
Beispielsweise:
Dies wird gedruckt:
quelle
Ein Beispiel, wie Sie Null vermeiden können, z. B. Filter vor groupingBy verwenden
Filtern Sie die Nullinstanzen vor groupingBy heraus.
Hier ist ein Beispielquelle