DistinctBy dans l'API Java Stream

1. Vue d'ensemble

La recherche de différents éléments dans une liste est l'une des tâches courantes auxquelles nous sommes confrontés en tant que programmeurs. À partir de Java 8 avec l'inclusion de Streams, nous avons une nouvelle API pour traiter les données en utilisant une approche fonctionnelle.

Dans cet article, nous allons montrer différentes alternatives au filtrage d'une collection à l'aide d'un attribut particulier d'objets dans la liste.

2. Utilisation de l'API Stream

L'API Stream fournit la méthode distinct () qui renvoie différents éléments d'une liste basée sur la méthode equals () de la classe Object .

Cependant, cela devient moins flexible si nous voulons filtrer par un attribut spécifique. L'une des alternatives que nous avons est d'écrire un filtre qui maintient l'état.

2.1. Utilisation d'un filtre avec état

L'une des solutions possibles serait d'implémenter un prédicat avec état :

public static  Predicate distinctByKey( Function keyExtractor) { Map seen = new ConcurrentHashMap(); return t -> seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null; }

Pour le tester, nous utiliserons la classe Person suivante qui a les attributs age , email et name:

public class Person { private int age; private String name; private String email; // standard getters and setters }

Et pour obtenir une nouvelle collection filtrée par nom , nous pouvons utiliser:

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

3. Utilisation des collections Eclipse

Eclipse Collections est une bibliothèque qui fournit des méthodes supplémentaires pour traiter les flux et les collections en Java.

3.1. Utilisation de ListIterate.distinct ()

La méthode ListIterate.distinct () nous permet de filtrer un Stream à l' aide de diverses HashingStrategies. Ces stratégies peuvent être définies à l'aide d'expressions lambda ou de références de méthode.

Si nous voulons filtrer par le nom de la personne :

List personListFiltered = ListIterate .distinct(personList, HashingStrategies.fromFunction(Person::getName));

Ou, si l'attribut que nous allons utiliser est primitif (int, long, double), nous pouvons utiliser une fonction spécialisée comme celle-ci:

List personListFiltered = ListIterate.distinct( personList, HashingStrategies.fromIntFunction(Person::getAge));

3.2. Dépendance de Maven

Nous devons ajouter les dépendances suivantes à notre pom.xml pour utiliser les collections Eclipse dans notre projet:

 org.eclipse.collections eclipse-collections 8.2.0 

Vous pouvez trouver la dernière version de la bibliothèque Eclipse Collections dans le référentiel Maven Central.

Pour en savoir plus sur cette bibliothèque, nous pouvons consulter cet article.

4. Utilisation de Vavr (J avaslang )

Il s'agit d'une bibliothèque fonctionnelle pour Java 8 qui fournit des données immuables et des structures de contrôle fonctionnelles.

4.1. Utilisation de List.distinctBy

Pour filtrer les listes, cette classe fournit sa propre classe List qui a la méthode distinctBy () qui nous permet de filtrer par attributs des objets qu'elle contient:

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

4.2. Dépendance de Maven

Nous ajouterons les dépendances suivantes à notre pom.xml pour utiliser Vavr dans notre projet.

 io.vavr vavr 0.9.0 

Vous pouvez trouver la dernière version de la bibliothèque Vavr dans le référentiel Maven Central.

Pour en savoir plus sur cette bibliothèque, nous pouvons consulter cet article.

5. Utilisation de StreamEx

Cette bibliothèque fournit des classes et des méthodes utiles pour le traitement des flux Java 8.

5.1. Utilisation de StreamEx.distinct

Dans les classes fournies se trouve StreamEx qui a la méthode distincte à laquelle nous pouvons envoyer une référence à l'attribut où nous voulons distinguer:

List personListFiltered = StreamEx.of(personList) .distinct(Person::getName) .toList();

5.2. Dépendance de Maven

Nous ajouterons les dépendances suivantes à notre pom.xml pour utiliser StreamEx dans notre projet.

 one.util streamex 0.6.5 

Vous pouvez trouver la dernière version de la bibliothèque StreamEx dans le référentiel Maven Central.

6. Conclusion

Dans ce rapide didacticiel, nous avons exploré des exemples sur la façon d'obtenir différents éléments d'un Stream, basés sur un attribut à l'aide de l'API Java 8 standard et des alternatives supplémentaires avec d'autres bibliothèques.

Comme toujours, le code complet est disponible à l'adresse over sur GitHub.