Comment filtrer une collection en Java

Comment filtrer une collection en Java

1. Vue d'ensemble

Dans ce court didacticiel,we’ll have a look at different ways of filtering a Collection in Java - c'est-à-dire trouver tous les éléments qui remplissent une certaine condition.

Il s'agit d'une tâche fondamentale présente dans pratiquement toutes les applications Java.

Pour cette raison, le nombre de bibliothèques offrant des fonctionnalités à cette fin est important.

En particulier, dans ce tutoriel, nous aborderons:

  • Fonctionfilter() de Java 8 Streams

  • Collecteur Java 9filtering

  • APIEclipse Collections pertinentes

  • MéthodeCollectionUtils filter() d'Apache

  • L'approcheCollections2 filter() de Guava

2. Utiliser des flux

Depuis l'introduction de Java 8,Streams a acquis un rôle clé dans la plupart des cas où nous devons traiter une collection de données.

Par conséquent, cette approche est privilégiée dans la plupart des cas car elle est construite en Java et ne nécessite aucune dépendance supplémentaire.

2.1. Filtrer une collection avecStreams

Par souci de simplicité,in all the examples our objective will be to create a method that retrieves only the even numbers from a Collection des valeursInteger.

Ainsi, nous pouvons exprimer la condition que nous utiliserons pour évaluer chaque élément comme «value % 2 == 0».

Dans tous les cas, nous devrons définir cette condition comme un objetPredicate:

public Collection findEvenNumbers(Collection baseCollection) {
    Predicate streamsPredicate = item -> item % 2 == 0;

    return baseCollection.stream()
      .filter(streamsPredicate)
      .collect(Collectors.toList());
}

Il est important de noter queeach library we analyze in this tutorial provides its own Predicate implementation, mais que tout de même, tous sont définis comme des interfaces fonctionnelles, ce qui nous permet d'utiliser les fonctions Lambda pour les déclarer.

Dans ce cas, nous avons utilisé unCollector prédéfini fourni par Java qui accumule les éléments dans unList, mais nous aurions pu en utiliser d'autres, comme indiqué dansthis previous post.

2.2. Filtrage après le regroupement d'une collection en Java 9

Les flux nous permettent d'agréger les éléments en utilisant lesgroupingBy collector.

Cependant, si nous filtrons comme nous l'avons fait dans la dernière section, certains éléments pourraient être ignorés à un stade précoce, avant que ce collectionneur n'entre en jeu.

Pour cette raison,the filtering collector was introduced with Java 9, with the objective of processing the subcollections after they have been grouped.

En suivant notre exemple, imaginons que nous souhaitons regrouper notre collection en fonction du nombre de chiffres de chaque Integer, avant de filtrer les nombres impairs:

public Map> findEvenNumbersAfterGrouping(
  Collection baseCollection) {

    Function getQuantityOfDigits = item -> (int) Math.log10(item) + 1;

    return baseCollection.stream()
      .collect(groupingBy(
        getQuantityOfDigits,
        filtering(item -> item % 2 == 0, toList())));
}

En bref, si nous utilisons ce collecteur, nous pourrions nous retrouver avec une entrée de valeur vide, alors que si nous filtrons avant le regroupement, le collecteur ne créerait pas du tout une telle entrée.

Bien entendu, nous choisirions l'approche en fonction de nos besoins.

3. Utilisation deEclipse Collections

Nous pouvons également utiliser d’autres bibliothèques tierces pour atteindre notre objectif, que ce soit parce que notre application ne prend pas en charge Java 8 ou parce que nous souhaitons profiter de fonctionnalités puissantes non fournies par Java.

C'est le cas deEclipse Collections, une bibliothèque qui s'efforce de suivre les nouveaux paradigmes, évoluant et intégrant les changements introduits par toutes les dernières versions de Java.

Nous pouvons commencer par explorer nosEclipse Collections Introductory post pour avoir une connaissance plus large des fonctionnalités fournies par cette bibliothèque.

3.1. Les dépendances

Commençons par ajouter la dépendance suivante auxpom.xml de notre projet:


    org.eclipse.collections
    eclipse-collections
    9.2.0

Leeclipse-collections inclut toutes les interfaces de structure de données nécessaires et l'API elle-même.

3.2. Filtrer une collection avecEclipse Collections

Utilisons maintenant la fonctionnalité de filtrage d'Eclipse sur l'une de ses structures de données, comme sesMutableList:

public Collection findEvenNumbers(Collection baseCollection) {
    Predicate eclipsePredicate
      = item -> item % 2 == 0;

    Collection filteredList = Lists.mutable
      .ofAll(baseCollection)
      .select(eclipsePredicate);

    return filteredList;
}

Comme alternative, nous aurions pu utiliser la méthode statiqueIterate deselect() pour définir l’objetfilteredList:

Collection filteredList
 = Iterate.select(baseCollection, eclipsePredicate);

4. Utilisation desCollectionUtils d'Apache

Pour commencer avec la bibliothèqueCollectionUtils d'Apache, nous pouvons consulterthis short tutorial où nous avons couvert ses utilisations.

Dans ce tutoriel, cependant, nous allons nous concentrer sur sa mise en œuvre de filter().

4.1. Les dépendances

Tout d'abord, nous aurons besoin des dépendances suivantes dans notre fichierpom.xml:


    org.apache.commons
    commons-collections4
    4.2

4.2. Filtrer une collection avecCollectionUtils

Nous sommes maintenant prêts à utiliser les méthodesCollectonUtils:

public Collection findEvenNumbers(Collection baseCollection) {
    Predicate apachePredicate = item -> item % 2 == 0;

    CollectionUtils.filter(baseCollection, apachePredicate);
    return baseCollection;
}

Nous devons tenir compte du fait que cette méthode modifie lesbaseCollection en supprimant chaque élément qui ne correspond pas à la condition.

Cela signifie quethe base Collection has to be mutable, otherwise it will throw an exception.

5. Utilisation desCollections2 de Guava

Comme précédemment, nous pouvons lire notre précédent article‘Filtering and Transforming Collections in Guava' pour plus d'informations à ce sujet.

5.1. Les dépendances

Commençons par ajouterthis dependency dans notre fichierpom.xml:


    com.google.guava
    guava
    25.1-jre

5.2. Filtrer une collection avecCollections2

Comme on peut le constater, cette approche est assez similaire à celle suivie dans la dernière section:

public Collection findEvenNumbers(Collection baseCollection) {
    Predicate guavaPredicate = item -> item % 2 == 0;

    return Collections2.filter(baseCollection, guavaPredicate);
}

Encore une fois, nous définissons ici un objetPredicate spécifique à Guava.

Dans ce cas, Guava ne modifie pas lesbaseCollection, il en génère un nouveau, nous pouvons donc utiliser une collection immuable comme entrée.

6. Conclusion

En résumé, nous avons vu qu'il existe de nombreuses façons différentes de filtrer les collections en Java.

Même si l'approche privilégiée est habituellement Stream, il est bon de connaître et de garder à l'esprit les fonctionnalités offertes par les autres bibliothèques.

Surtout si nous devons prendre en charge les anciennes versions de Java. Toutefois, si tel est le cas, nous devons garder à l'esprit les fonctionnalités Java récentes utilisées tout au long du didacticiel, telles que les lambdas doivent être remplacées par des classes anonymes.

Comme d'habitude, nous pouvons trouver tous les exemples présentés dans ce tutoriel dans nosGithub repo.