DistinctBy in de Java Stream API

1. Overzicht

Het zoeken naar verschillende elementen in een lijst is een van de meest voorkomende taken waarmee wij als programmeurs gewoonlijk worden geconfronteerd. Vanaf Java 8 met de toevoeging van Streams we hebben een nieuwe API om gegevens te verwerken met behulp van een functionele aanpak.

In dit artikel laten we verschillende alternatieven zien voor het filteren van een verzameling met een bepaald kenmerk van objecten in de lijst.

2. Met behulp van de Stream API

De Stream API biedt de onderscheiden () methode die verschillende elementen van een lijst retourneert op basis van de is gelijk aan () methode van de Voorwerp klasse.

Het wordt echter minder flexibel als we willen filteren op een specifiek kenmerk. Een van de alternatieven die we hebben, is om een ​​filter te schrijven dat de staat handhaaft.

2.1. Met behulp van een stateful filter

Een van de mogelijke oplossingen zou zijn om een ​​stateful te implementeren Predikaat:

openbaar statisch predikaat distinctByKey (Function keyExtractor) {Map seen = new ConcurrentHashMap (); retourneer t -> seen.putIfAbsent (keyExtractor.apply (t), Boolean.TRUE) == null; }

Om het te testen, gebruiken we het volgende Persoon klasse met de attributen leeftijd, e-mail, en naam:

openbare klasse Persoon {privé int. leeftijd; private String naam; privé String-e-mail; // standaard getters en setters}

En om een ​​nieuwe gefilterde verzameling te krijgen door naam, we kunnen gebruiken:

Lijst personListFiltered = personList.stream () .filter (distinctByKey (p -> p.getName ())) .collect (Collectors.toList ());

3. Eclipse-verzamelingen gebruiken

Eclipse Collections is een bibliotheek die aanvullende verwerkingsmethoden biedt Streams en verzamelingen in Java.

3.1. De ... gebruiken ListIterate.distinct ()

De ListIterate.distinct () methode stelt ons in staat om een Stroom met behulp van verschillende HashingStrategies. Deze strategieën kunnen worden gedefinieerd met behulp van lambda-expressies of methodeverwijzingen.

Als we willen filteren op de Personen naam:

Lijst personListFiltered = ListIterate .distinct (personList, HashingStrategies.fromFunction (Persoon :: getName));

Of, als het attribuut dat we gaan gebruiken primitief is (int, long, double), kunnen we een gespecialiseerde functie zoals deze gebruiken:

Lijst personListFiltered = ListIterate.distinct (personList, HashingStrategies.fromIntFunction (Persoon :: getAge));

3.2. Afhankelijkheid van Maven

We moeten de volgende afhankelijkheden toevoegen aan onze pom.xml om Eclipse Collections te gebruiken in ons project:

 org.eclipse.collections eclipse-collections 8.2.0 

U kunt de nieuwste versie van de Eclipse Collections-bibliotheek vinden in de Maven Central-repository.

Voor meer informatie over deze bibliotheek kunnen we naar dit artikel gaan.

4. Vavr (Javaslang)

Dit is een functionele bibliotheek voor Java 8 die onveranderlijke gegevens en functionele controlestructuren biedt.

4.1. Gebruik makend van List.distinctBy

Om lijsten te filteren, biedt deze klasse zijn eigen List-klasse met de extensie distinctBy () methode waarmee we kunnen filteren op attributen van de objecten die het bevat:

Lijst personListFiltered = List.ofAll (personList) .distinctBy (Persoon :: getName) .toJavaList ();

4.2. Afhankelijkheid van Maven

We zullen de volgende afhankelijkheden toevoegen aan onze pom.xml om Vavr in ons project te gebruiken.

 io.vavr vavr 0.9.0 

U kunt de nieuwste versie van de Vavr-bibliotheek vinden in de Maven Central-repository.

Voor meer informatie over deze bibliotheek kunnen we naar dit artikel gaan.

5. StreamEx gebruiken

Deze bibliotheek biedt handige klassen en methoden voor de verwerking van Java 8-streams.

5.1. Gebruik makend van StreamEx. Onderscheidend

Binnen de aangeboden lessen is StreamEx die heeft de onderscheiden methode waarnaar we een verwijzing kunnen sturen naar het attribuut waar we het willen onderscheiden:

Lijst personListFiltered = StreamEx.of (personList) .distinct (Persoon :: getName) .toList ();

5.2. Afhankelijkheid van Maven

We zullen de volgende afhankelijkheden toevoegen aan onze pom.xml om StreamEx in ons project te gebruiken.

 one.util streamex 0.6.5 

U kunt de nieuwste versie van de StreamEx-bibliotheek vinden in de Maven Central-repository.

6. Conclusie

In deze korte tutorial hebben we voorbeelden onderzocht van hoe je verschillende elementen van een stream kunt krijgen, op basis van een attribuut met behulp van de standaard Java 8 API en aanvullende alternatieven met andere bibliotheken.

Zoals altijd is de volledige code beschikbaar op GitHub.