2016-07-19 5 views
3

Wenn ich ein Stream<@Nullable Object> habe, kann ich null-Elemente wie das Filter:Filter nullable Werte von Strom und Aktualisierung der Nullable-Eigenschaft

Stream<@Nullable Object> s = str.filter(Objects::nonNull); 

Dies ist jedoch liefert einen Strom von Nullable-Objects. Gibt es eine elegante Möglichkeit, einen Stream von NonNull-Elementen zurückzugeben? An dieser Stelle weiß ich bereits, dass die Elemente nicht null sein können.

Dies ist, was ich habe kommen mit, aber es ist zu lang, imo:

Stream<@NonNull Object> s = str.map(Optional::ofNullable).filter(Optional::isPresent).map(Optional::get) 

(Dies bedeutet, dass Optional :: immer ungleich NULL-Werte zurück zu bekommen)

+1

'str.filter (Objekte :: nonNull) .map (Objekte :: requireNonNull)' ... – Holger

Antwort

2

Nun, alle Lösungen basierend auf Optional oder Objects gehen davon aus, dass der Prüfer die Semantik seiner Methoden kennt, da sie keine expliziten Anmerkungen haben.

Da filter nie die Art verändert, wäre es tiefe Unterstützung der Prüfer erfordert dies als Stream<@Nullable X>Stream<@NonNull X> Übergang zu modellieren, auch wenn es um die Semantik der Filterfunktion versteht.

Je einfacher Ansatz ist map zu verwenden, da es den Elementtyp erlaubt das Ändern:

Stream<@NonNull Object> s = str.filter(Objects::nonNull).map(Objects::requireNonNull); 

Hier sorgt die Filteroperation, dass es keine null Elemente, aber den formalen nicht Elementtyp ändern. Im Gegensatz dazu ermöglicht die Operation map das Ändern des formalen Typs, und die Funktion Objects::requireNonNull konvertiert eine nullable-fähige Eingabe in eine nonnull-Ausgabe, vorausgesetzt, das Audit-Tool weiß dies, da diese JRE-Methoden keine Anmerkungen enthalten.

Da requireNonNull eine Ausnahme für null Werte werfen, nur die Kombination von filter und map ermöglicht das gewünschte Verhalten null Werte entfernen und den formalen Elementtyp verändern.

Wenn das Audit-Tool, um die Semantik der JRE-Methode nicht versteht, werden Sie eine entsprechende Methode selbst, dann mit den Anmerkungen zum Erstellen,

class MyObjUtil { 
    public static <T> @NonNull T requireNonNull(@Nullable T obj) { 
     if(obj==null) throw new NullPointerException(); 
     return obj; 
    } 
} 

, die als korrekt durch eine vernünftige anerkannt werden sollen

: Checker, und verwenden sie es als

Stream<@NonNull Object> s = str.filter(Objects::nonNull).map(MyObjUtil::requireNonNull); 

Ihr Optional basierten Ansatz kann mit Java 9 vereinfacht werden

Stream<@NonNull Object> s = str.flatMap(o -> Optional.ofNullable(o).stream()); 

, die noch weiter vereinfacht werden kann:

Stream<@NonNull Object> s = str.flatMap(o -> Stream.ofNullable(o)); 

aber natürlich erfordert dies wiederum ein Werkzeug, um diese Methoden zu verstehen.Oder Sie neu implementieren die Logik:

class MyStreamUtil { 
    public static <T> Stream<@NonNull T> ofNullable(@Nullable T obj) { 
     return obj==null? Stream.empty(): Stream.of(obj); 
    } 
} 
Stream<@NonNull Object> s = str.flatMap(o -> MyStreamUtil.ofNullable(o)); 

die dann unter Java 8 als gut funktioniert.

+0

Ich bezweifle, dass es eine bessere Antwort gibt, also werde ich Ihre Antwort akzeptieren. Vielen Dank! – looper