Java – Filtern Sie einen Stream mit Lambda-Ausdrücken PlatoBlockchain Data Intelligence. Vertikale Suche. Ai.

Java – Filtern Sie einen Stream mit Lambda-Ausdrücken

Java Streams wurden bereits in Java 8 im Jahr 2014 eingeführt, um wortreiches Java in ein Paradigma der funktionalen Programmierung einzuführen. Java-Streams stellen viele flexible und leistungsstarke funktionale Operationen bereit, um die Sammlungsverarbeitung in Einzeilern durchzuführen.

Das Filtern von Sammlungen basierend auf einem Prädikat bleibt eine der am häufigsten verwendeten funktionalen Operationen und kann mit a durchgeführt werden Predicate oder kürzer – mit a Lambda-Ausdruck.

In dieser kurzen Anleitung sehen wir uns an, wie Sie einen Java 8-Stream mit Lambda-Ausdrücken filtern können.

Filtern von Streams in Java

Im Allgemeinen jede Stream kann über die gefiltert werden filter() Methode und ein gegebenes Prädikat:

Stream filter(Predicate<? super T> predicate)

Jedes Element im Stream wird gegen das Prädikat ausgeführt und dem Ausgabestream hinzugefügt, wenn das Prädikat zurückgegeben wird true. Sie können eine liefern Predicate Beispiel:

Predicate contains = s -> s.contains("_deprecated");
List results = stream.filter(contains).collect(Collectors.toList());

Oder vereinfachen Sie es, indem Sie einen Lambda-Ausdruck bereitstellen:

List results = stream.filter(s -> s.contains("_deprecated"))
                             .collect(Collectors.toList());

Oder reduzieren Sie sogar den Lambda-Ausdruck in a Methodenreferenz:


List results = stream.filter(String::isEmpty)
                             .collect(Collectors.toList());

Mit Methodenreferenzen können Sie keine Argumente übergeben, aber Sie können Methoden in dem Objekt definieren, das Sie filtern, und sie so anpassen, dass sie leicht filterbar sind (solange die Methode keine Argumente akzeptiert und eine boolean).

Beachten Sie, dass Streams sind keine Sammlungen – sie sind Ströme von Sammlungen, und Sie müssen sie wieder in eine beliebige Sammlung wie a einsammeln List, Mapusw., um ihnen Beständigkeit zu verleihen. Darüber hinaus werden auch alle Operationen an Stream-Elementen ausgeführt Zwischen- or Terminal:

  • Zwischenoperationen geben einen neuen Stream mit Änderungen gegenüber der vorherigen Operation zurück
  • Terminaloperationen geben einen Datentyp zurück und sollen eine Verarbeitungspipeline in einem Stream beenden

filter() ist ein Zwischen- Operation und soll mit anderen Zwischenoperationen verkettet werden, bevor der Stream beendet wird. Um Änderungen (z. B. Änderungen an Elementen selbst oder gefilterte Ergebnisse) beizubehalten, müssen Sie das Ergebnis zuweisen Ausgabestrom zu einer neuen Referenzvariablen, durch eine Terminaloperation.

Hinweis: Selbst wenn Sie viele Lambda-Ausdrücke verketten, treten bei korrekten Zeilenumbrüchen möglicherweise keine Lesbarkeitsprobleme auf.

In den folgenden Beispielen arbeiten wir mit dieser Bücherliste:

Book book1 = new Book("001", "Our Mathematical Universe", "Max Tegmark", 432, 2014);
Book book2 = new Book("002", "Life 3.0", "Max Tegmark", 280, 2017);
Book book3 = new Book("003", "Sapiens", "Yuval Noah Harari", 443, 2011);
        
List books = Arrays.asList(book1, book2, book3);

Sammlung mit Stream.filter() filtern

Lassen Sie uns diese Büchersammlung filtern. Jedes Prädikat geht – also filtern wir zum Beispiel danach, welche Bücher mehr als 400 Seiten haben:

List results = books.stream()
                          .filter(b -> b.getPageNumber() > 400)
                          .collect(Collectors.toList());

Das Ergebnis ist eine Liste, die Folgendes enthält:

[
Book{id='001', name='Our Mathematical Universe', author='Max Tegmark', pageNumber=432, publishedYear=2014}, 
Book{id='003', name='Sapiens', author='Yuval Noah Harari', pageNumber=443, publishedYear=2011}
]

Beim Filtern ist eine wirklich nützliche Methode zum Verketten map(), mit dem Sie Objekte einem anderen Wert zuordnen können. Beispielsweise können wir jedes Buch seinem Namen zuordnen und so nur die zurückgeben Namen der Bücher, die auf das Prädikat aus dem passen filter() Anruf:

List results = books.stream()
                            .filter(b -> b.getPageNumber() > 400)
                            .map(Book::getName)
                            .collect(Collectors.toList());

Dies führt zu einer Liste von Zeichenfolgen:

[Our Mathematical Universe, Sapiens]

Filtersammlung für mehrere Prädikate mit Stream.filter()

Normalerweise möchten wir Sammlungen nach mehr als einem Kriterium filtern. Dies kann durch Verketten mehrerer erfolgen filter() Anrufe or Verwenden eines Kurzschlussprädikats, das zwei Bedingungen in einer einzigen prüft filter() Anruf.

 List results = books.stream()
                    .filter(b -> b.getPageNumber() > 400 && b.getName().length() > 10)
                    .collect(Collectors.toList());
                    


 List results2 = books.stream()
                    .filter(b -> b.getPageNumber() > 400)
                    .filter(b -> b.getName().length() > 10)
                    .collect(Collectors.toList());

Sehen Sie sich unseren praxisnahen, praktischen Leitfaden zum Erlernen von Git an, mit Best Practices, branchenweit akzeptierten Standards und einem mitgelieferten Spickzettel. Hören Sie auf, Git-Befehle zu googeln und tatsächlich in Verbindung, um es!

Bei Verwendung mehrerer Kriterien können die Lambda-Aufrufe etwas langwierig werden. An dieser Stelle könnte es mehr Klarheit bieten, sie als eigenständige Prädikate zu extrahieren. Doch welcher Ansatz ist schneller?

Einzelner Filter mit komplexer Bedingung oder mehrere Filter?

Es hängt von Ihrer Hardware ab, wie groß Ihre Sammlung ist und ob Sie parallele Streams verwenden oder nicht. Im Allgemeinen übertrifft ein Filter mit einer komplexen Bedingung mehrere Filter mit einfacheren Bedingungen (kleine bis mittlere Sammlungen) oder die gleiche Leistung (sehr große Sammlungen). Wenn Ihre Bedingungen zu lang sind, können Sie davon profitieren, sie auf mehrere zu verteilen filter() fordert die verbesserte Lesbarkeit, da die Leistung sehr ähnlich ist.

Die beste Wahl ist, beide auszuprobieren, beachten Sie die Leistung auf der Zielgerät, und passen Sie Ihre Strategie entsprechend an.

GitHub-Benutzer Volkodavs hat einen Filter-Benchmark in Durchsatzoperationen/s durchgeführt und die Ergebnisse auf der gehostet „Javafilter-Benchmarks“ Repository. Die Ergebnisse sind in einer informativen Tabelle zusammengefasst:

Es zeigt einen deutlichen Rückgang der Renditen bei größeren Sammlungsgrößen, wobei beide Ansätze ungefähr auf dem gleichen Niveau abschneiden. Parallele Streams profitieren bei größeren Sammlungsgrößen erheblich, beeinträchtigen jedoch die Leistung bei kleineren Größen (unter ~ 10 Elementen). Es ist erwähnenswert, dass parallele Streams ihren Durchsatz viel besser beibehalten als nicht-parallele Streams, wodurch sie wesentlich robuster gegenüber Eingaben sind.

Zeitstempel:

Mehr von Stapelmissbrauch