DistinctBy in der Java Stream API
1. Überblick
Die Suche nach verschiedenen Elementen in einer Liste ist eine der häufigsten Aufgaben, mit denen wir als Programmierer normalerweise konfrontiert sind. Ab Java 8 haben wir unter Einbeziehung vonStreams eine neue API zur Verarbeitung von Daten mithilfe eines funktionalen Ansatzes.
In diesem Artikel werden verschiedene Alternativen zum Filtern einer Sammlung anhand eines bestimmten Attributs von Objekten in der Liste gezeigt.
2. Verwenden der Stream-API
Die Stream-API stellt die Methodedistinct()bereit, die verschiedene Elemente einer Liste basierend auf der Methodeequals()der KlasseObjectzurückgibt.
Es wird jedoch weniger flexibel, wenn wir nach einem bestimmten Attribut filtern möchten. Eine der Alternativen besteht darin, einen Filter zu schreiben, der den Zustand beibehält.
2.1. Verwenden eines Stateful-Filters
Eine der möglichen Lösungen wäre die Implementierung eines StatefulPredicate:
public static Predicate distinctByKey(
Function super T, ?> keyExtractor) {
Map
Zum Testen verwenden wir die folgende KlassePerson mit den Attributenage,email undname:
public class Person {
private int age;
private String name;
private String email;
// standard getters and setters
}
Und um eine neue gefilterte Sammlung nachname zu erhalten, können wir Folgendes verwenden:
List personListFiltered = personList.stream()
.filter(distinctByKey(p -> p.getName()))
.collect(Collectors.toList());
3. Verwenden von Eclipse-Sammlungen
Eclipse Collections ist eine Bibliothek, die zusätzliche Methoden zur Verarbeitung vonStreams und Sammlungen in Java bereitstellt.
3.1. Verwenden SieListIterate.distinct()
Mit der MethodeListIterate.distinct() können wirStream mit verschiedenenHashingStrategies. filtern. Diese Strategien können mithilfe von Lambda-Ausdrücken oder Methodenreferenzen definiert werden.
Wenn wir nach dem Namen vonPerson’sfiltern möchten:
List personListFiltered = ListIterate
.distinct(personList, HashingStrategies.fromFunction(Person::getName));
Wenn das Attribut, das wir verwenden möchten, primitiv ist (int, long, double), können wir eine spezielle Funktion wie die folgende verwenden:
List personListFiltered = ListIterate.distinct(
personList, HashingStrategies.fromIntFunction(Person::getAge));
3.2. Maven-Abhängigkeit
Wir müssen unserenpom.xml die folgenden Abhängigkeiten hinzufügen, um Eclipse-Sammlungen in unserem Projekt verwenden zu können:
org.eclipse.collections
eclipse-collections
8.2.0
Die neueste Version der Eclipse Collections-Bibliothek finden Sie im Repository vonMaven Central.
Um mehr über diese Bibliothek zu erfahren, gehen Sie zuthis article.
4. Using Vavr (Javaslang *) *
Dies ist eine Funktionsbibliothek für Java 8, die unveränderliche Daten und Funktionskontrollstrukturen bereitstellt.
4.1. Verwenden vonList.distinctBy
Zum Filtern von Listen stellt diese Klasse eine eigene List-Klasse bereit, die über die MethodedistinctBy()verfügt, mit der wir nach Attributen der darin enthaltenen Objekte filtern können:
List personListFiltered = List.ofAll(personList)
.distinctBy(Person::getName)
.toJavaList();
4.2. Maven-Abhängigkeit
Wir werden die folgenden Abhängigkeiten zu unserenpom.xmlhinzufügen, um Vavr in unserem Projekt zu verwenden.
io.vavr
vavr
0.9.0
Sie finden die neueste Version der Vavr-Bibliothek im Repository vonMaven Central.
Um mehr über diese Bibliothek zu erfahren, gehen Sie zuthis article.
5. Verwenden von StreamEx
Diese Bibliothek bietet nützliche Klassen und Methoden für die Verarbeitung von Java 8-Streams.
5.1. Verwenden vonStreamEx.distinct
Innerhalb der bereitgestellten Klassen befindet sichStreamEx mit der Methodedistinct, an die wir einen Verweis auf das Attribut senden können, bei dem wir unterscheiden möchten:
List personListFiltered = StreamEx.of(personList)
.distinct(Person::getName)
.toList();
5.2. Maven-Abhängigkeit
Wir werden die folgenden Abhängigkeiten zu unserenpom.xmlhinzufügen, um StreamEx in unserem Projekt zu verwenden.
one.util
streamex
0.6.5
Sie finden die neueste Version der StreamEx-Bibliothek im Repository vonMaven Central.
6. Fazit
In diesem kurzen Lernprogramm haben wir Beispiele untersucht, wie verschiedene Elemente eines Streams basierend auf einem Attribut unter Verwendung der Standard-Java 8-API und zusätzlichen Alternativen mit anderen Bibliotheken abgerufen werden können.
Wie immer ist der vollständige Codeover on GitHub verfügbar.