DistinctBy i Java Stream API
1. Oversikt
Å søke etter forskjellige elementer i en liste er en av de vanlige oppgavene som vi som programmerere vanligvis står overfor. Fra Java 8 med inkludering av Strømmer vi har en ny API for å behandle data ved hjelp av funksjonell tilnærming.
I denne artikkelen viser vi forskjellige alternativer til å filtrere en samling ved hjelp av et bestemt attributt av objekter i listen.
2. Bruke Stream API
Stream API gir distinkt() metode som returnerer forskjellige elementer i en liste basert på er lik() metoden for Gjenstand klasse.
Imidlertid blir det mindre fleksibelt hvis vi vil filtrere etter et bestemt attributt. Et av alternativene vi har er å skrive et filter som opprettholder staten.
2.1. Bruke et stateful filter
En av de mulige løsningene vil være å implementere en stateful Predikat:
public static Predicate distinctByKey (Function keyExtractor) {Map seen = new ConcurrentHashMap (); return t -> seen.putIfAbsent (keyExtractor.apply (t), Boolean.TRUE) == null; }
For å teste det, bruker vi følgende Person klasse som har attributtene alder, e-post, og Navn:
offentlig klasse Person {privat int alder; privat strengnavn; privat streng e-post; // standard getters og setters}
Og for å få en ny filtrert samling av Navn, Vi kan bruke:
Liste personListFiltered = personList.stream () .filter (distinctByKey (p -> p.getName ())) .collect (Collectors.toList ());
3. Bruke formørkelsamlinger
Eclipse Collections er et bibliotek som gir flere metoder for behandling Strømmer og samlinger i Java.
3.1. Bruker ListIterate.distinct ()
De ListIterate.distinct () metoden lar oss filtrere a Strøm bruker forskjellige HashingStrategies. Disse strategiene kan defineres ved hjelp av lambdauttrykk eller metodereferanser.
Hvis vi vil filtrere etter Personens Navn:
List personListFiltered = ListIterate .distinct (personList, HashingStrategies.fromFunction (Person :: getName));
Eller hvis attributtet vi skal bruke er primitiv (int, lang, dobbel), kan vi bruke en spesialfunksjon som denne:
List personListFiltered = ListIterate.distinct (personList, HashingStrategies.fromIntFunction (Person :: getAge));
3.2. Maven avhengighet
Vi må legge til følgende avhengigheter i vår pom.xml å bruke Eclipse Collections i prosjektet vårt:
org.eclipse.collections formørkelsesamlinger 8.2.0
Du finner den siste versjonen av Eclipse Collections-biblioteket i Maven Central-arkivet.
For å lære mer om dette biblioteket kan vi gå til denne artikkelen.
4. Bruke Vavr (Javaslang)
Dette er et funksjonelt bibliotek for Java 8 som gir uforanderlige data og funksjonelle kontrollstrukturer.
4.1. Ved hjelp av List.distinctBy
For å filtrere lister, gir denne klassen sin egen listeklasse som har distinkt av () metode som lar oss filtrere etter attributter til objektene den inneholder:
List personListFiltered = List.ofAll (personList) .distinctBy (Person :: getName) .toJavaList ();
4.2. Maven avhengighet
Vi vil legge til følgende avhengigheter i vår pom.xml å bruke Vavr i prosjektet vårt.
io.vavr vavr 0.9.0
Du finner den nyeste versjonen av Vavr-biblioteket i Maven Central-arkivet.
For å lære mer om dette biblioteket kan vi gå til denne artikkelen.
5. Bruke StreamEx
Dette biblioteket gir nyttige klasser og metoder for behandling av Java 8-strømmer.
5.1. Ved hjelp av StreamEx. Tydelig
Innenfor klassene som tilbys er StreamEx som har distinkt metode som vi kan sende en referanse til attributtet der vi vil skille:
Liste personListFiltered = StreamEx.of (personList) .distinct (Person :: getName) .toList ();
5.2. Maven avhengighet
Vi vil legge til følgende avhengigheter i vår pom.xml å bruke StreamEx i prosjektet vårt.
one.util streamex 0.6.5
Du finner den siste versjonen av StreamEx-biblioteket i Maven Central-arkivet.
6. Konklusjon
I denne raske opplæringen utforsket vi eksempler på hvordan du får forskjellige elementer i en Stream, basert på et attributt ved hjelp av standard Java 8 API og tilleggsalternativer med andre biblioteker.
Som alltid er den komplette koden tilgjengelig på GitHub.