2017-05-17 9 views
0

Ist es möglich, mehrmals in einem Stream zu filtern? Zum Beispiel, wenn ich eine Liste mit IDs habe und ich eine HashMap streamen und den Schlüssel der HashMap zuordnen möchte, um eine Liste einzugeben und wo sie übereinstimmen, möchte ich das Objekt aus der HashMap holen und es zum Beispiel erneut filtern int-Feld in dem Objekt, das zum Beispiel größer als 3 ist, und summiert sie am Ende. Wenn zum Beispiel 10 Fälle gefunden wurden, in denen der Schlüssel der Liste und der HashMap-Schlüssel gleich sind und diese 10 Fälle filtern und 3 Fälle bilden, bei denen zum Beispiel ein int-Feld größer als 3 ist, gibt es am Ende eine Summe von diesen zurück.Filter öfter in einem Java 8 Stream

Hier ist mein Code so weit: Wenn ich versuche, um die Liste des Ergebnisses dieses ich diese erhalten zu drucken: [email protected]

somemap.entrySet().stream().filter(e -> aListContainingIds.contains(e.getKey())) 
      .map(Map.Entry::getValue) 
      .map(n -> n.getTheOtherListFromMatchedValue().stream().filter(n -> n.getAnIntFieldFromObject() > 3)) 
      .collect(Collectors.toList()); 
+6

warum versuchst du es nicht? –

+1

Ich würde sagen: ja, es ist möglich (* ironie aus *) zeige uns ein paar Code, was du versucht hast –

+0

Ich habe den Code, den ich bisher versucht habe, hinzugefügt. –

Antwort

3

Ich glaube, Sie sollten verwenden Stream.flatMaptoInt (oder Stream.flatMaptoLong) statt nur map:

int total = somemap.entrySet().stream() 
    .filter(e -> aListContainingIds.contains(e.getKey())) 
    .map(Map.Entry::getValue) 
    .flatMapToInt(value -> value.getTheOtherListFromMatchedValue().stream()) 
    .filter(n -> n.getAnIntFieldFromObject() > 3) 
    .sum(); 

Im allgemeinen flatMapToInt (oder flatMap, wenn die Stromelemente instanc sind (Es ist eine Klasse anstelle von Primitiven), wenn die Funktion, die Sie anwenden, einen anderen Stream zurückgibt und Sie wollen, dass die Elemente dieses Streams Teil des ursprünglichen Streams sind.

Am Ende können Sie die Summe mit der IntStream.sum Methode erhalten.

+2

Ich denke, es wird einfacher zu lesen, wenn du den '.filter (...)' Schritt aus der 'flatMap' Funktion entfernst. Es gibt keinen funktionalen Unterschied, aber die "flatMap" -Funktion passt in eine Zeile und der nachfolgende "Filter" benötigt keine andere Einrückung. – Holger

+0

@Holger Guter Punkt, danke. Aber bist du dir absolut sicher, dass es auch bei einem parallelen Stream keinen Unterschied gibt? Ich meine, nicht nur funktional, sondern auch, wie sich der Stream entfaltet –

+3

Wenn überhaupt, würde ich annehmen, dass das Verschieben des 'Filters' in den äußeren Strom es effizienter macht. Wenn Ihr Prädikat ein erfassender Lambda-Ausdruck ist, erzeugt das Vorhandensein in der Funktion 'flatMap' eine neue Instanz für jedes Element des äußeren Datenstroms, während es beim äußeren Datenstrom eine einzige Prädikat-Instanz für die gesamte Operation erstellt. Ähnliche Effekte sind anzunehmen, wenn der summierende Consumer mit der Filteroperation innerhalb der Stream-Implementierung fusioniert wird. Ich sage nicht, dass der Effekt auffällt ... – Holger