DistinctBy dans l’API Java Stream

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 généralement confrontés en tant que programmeurs. A partir de Java 8 avec l'inclusion deStreams, 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 des objets de la liste.

2. Utilisation de l'API Stream

L'API Stream fournit la méthodedistinct() qui renvoie différents éléments d'une liste basée sur la méthodeequals() de la classeObject.

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

Une des solutions possibles serait d'implémenter unPredicate: 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 classePerson suivante qui a les attributsage,email etname:

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

Et pour obtenir une nouvelle collection filtrée parname, 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 le traitement desStreams et des collections en Java.

3.1. Utilisation desListIterate.distinct()

La méthodeListIterate.distinct() nous permet de filtrer unStream en utilisant diversHashingStrategies. 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 nomPerson’s:

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 Maven

Nous devons ajouter les dépendances suivantes à nospom.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érentielMaven Central.

Pour en savoir plus sur cette bibliothèque, nous pouvons aller àthis article.

4. Using Vavr (Javaslang *) *

Cette bibliothèque fonctionnelle pour Java 8 fournit des données immuables et des structures de contrôle fonctionnelles.

4.1. Utilisation deList.distinctBy

Pour filtrer les listes, cette classe fournit sa propre classe List qui a la méthodedistinctBy() 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 Maven

Nous ajouterons les dépendances suivantes à nospom.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érentielMaven Central.

Pour en savoir plus sur cette bibliothèque, nous pouvons aller àthis 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 deStreamEx.distinct

Dans les classes fournies se trouveStreamEx qui a la méthodedistinct à 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 Maven

Nous ajouterons les dépendances suivantes à nospom.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érentielMaven Central.

6. Conclusion

Dans ce rapide didacticiel, nous avons exploré des exemples permettant d’obtenir différents éléments d’un flux en fonction d’un attribut utilisant l’API standard Java 8 et d’autres alternatives avec d’autres bibliothèques.

Comme toujours, le code complet est disponibleover on GitHub.