Chaîne de prédicat Java 8

1. Vue d'ensemble

Dans ce rapide didacticiel, nous aborderons différentes manières de chaîner des prédicats dans Java 8.

2. Exemple de base

Voyons d'abord comment utiliser un simple prédicat pour filtrer une liste de noms:

@Test public void whenFilterList_thenSuccess(){ List names = Arrays.asList("Adam", "Alexander", "John", "Tom"); List result = names.stream() .filter(name -> name.startsWith("A")) .collect(Collectors.toList()); assertEquals(2, result.size()); assertThat(result, contains("Adam","Alexander")); }

Dans cet exemple, nous avons filtré notre liste de noms pour ne laisser que les noms commençant par «A» à l'aide du prédicat :

name -> name.startsWith("A")

Mais que faire si nous voulions appliquer plusieurs prédicats ?

3. Filtres multiples

Si nous voulions appliquer plusieurs prédicats , une option consiste simplement à enchaîner plusieurs filtres:

@Test public void whenFilterListWithMultipleFilters_thenSuccess(){ List result = names.stream() .filter(name -> name.startsWith("A")) .filter(name -> name.length() < 5) .collect(Collectors.toList()); assertEquals(1, result.size()); assertThat(result, contains("Adam")); }

Nous avons maintenant mis à jour notre exemple pour filtrer notre liste en extrayant les noms qui commencent par «A» et ont une longueur inférieure à 5.

Nous avons utilisé deux filtres - un pour chaque prédicat .

4. Prédicat complexe

Maintenant, au lieu d'utiliser plusieurs filtres, nous pouvons utiliser un filtre avec un prédicat complexe :

@Test public void whenFilterListWithComplexPredicate_thenSuccess(){ List result = names.stream() .filter(name -> name.startsWith("A") && name.length() < 5) .collect(Collectors.toList()); assertEquals(1, result.size()); assertThat(result, contains("Adam")); }

Cette option est plus flexible que la première, car nous pouvons utiliser des opérations au niveau du bit pour créer le prédicat aussi complexe que nous le souhaitons.

5. Combinaison de prédicats

Ensuite, si nous ne voulons pas créer un prédicat complexe à l' aide d'opérations au niveau du bit, Java 8 Predicate a des méthodes utiles que nous pouvons utiliser pour combiner des prédicats .

Nous allons combiner les prédicats en utilisant les méthodes Predicate.and () , Predicate.or () et Predicate.negate ().

5.1. Prédicat.et ()

Dans cet exemple, nous définirons explicitement nos prédicats , puis nous les combinerons en utilisant Predicate.and ():

@Test public void whenFilterListWithCombinedPredicatesUsingAnd_thenSuccess(){ Predicate predicate1 = str -> str.startsWith("A"); Predicate predicate2 = str -> str.length() < 5; List result = names.stream() .filter(predicate1.and(predicate2)) .collect(Collectors.toList()); assertEquals(1, result.size()); assertThat(result, contains("Adam")); }

Comme on peut le voir, la syntaxe est assez intuitive, et les noms des méthodes suggèrent le type d'opération. En utilisant et () , nous avons filtré notre liste en extrayant uniquement les noms qui remplissent les deux conditions.

5.2. Prédicat.ou ()

Nous pouvons également utiliser Predicate.or () pour combiner des prédicats.

Extrayons les noms commençant par «J», ainsi que les noms d'une longueur inférieure à 4:

@Test public void whenFilterListWithCombinedPredicatesUsingOr_thenSuccess(){ Predicate predicate1 = str -> str.startsWith("J"); Predicate predicate2 = str -> str.length() < 4; List result = names.stream() .filter(predicate1.or(predicate2)) .collect(Collectors.toList()); assertEquals(2, result.size()); assertThat(result, contains("John","Tom")); }

5.3. Predicate.negate ()

Nous pouvons également utiliser Predicate.negate () lors de la combinaison de nos prédicats :

@Test public void whenFilterListWithCombinedPredicatesUsingOrAndNegate_thenSuccess(){ Predicate predicate1 = str -> str.startsWith("J"); Predicate predicate2 = str -> str.length() < 4; List result = names.stream() .filter(predicate1.or(predicate2.negate())) .collect(Collectors.toList()); assertEquals(3, result.size()); assertThat(result, contains("Adam","Alexander","John")); }

Ici, nous avons utilisé une combinaison de or () et negate () pour filtrer la liste par des noms commençant par «J» ou ayant une longueur qui n'est pas inférieure à 4.

5.4. Combiner les prédicats en ligne

Nous n'avons pas besoin de définir explicitement nos prédicats à utiliser et (), ou () , et negate ().

Nous pouvons également les utiliser en ligne en lançant le prédicat :

@Test public void whenFilterListWithCombinedPredicatesInline_thenSuccess(){ List result = names.stream() .filter(((Predicate)name -> name.startsWith("A")) .and(name -> name.length()<5)) .collect(Collectors.toList()); assertEquals(1, result.size()); assertThat(result, contains("Adam")); }

6. Combinaison d'une collection de prédicats

Enfin, voyons comment chaîner une collection de Prédicats en les réduisant.

Dans l'exemple suivant, nous avons une liste de prédicats que nous avons combinés à l'aide de Predicate.and () :

@Test public void whenFilterListWithCollectionOfPredicatesUsingAnd_thenSuccess(){ List
    
      allPredicates = new ArrayList
     
      (); allPredicates.add(str -> str.startsWith("A")); allPredicates.add(str -> str.contains("d")); allPredicates.add(str -> str.length() > 4); List result = names.stream() .filter(allPredicates.stream().reduce(x->true, Predicate::and)) .collect(Collectors.toList()); assertEquals(1, result.size()); assertThat(result, contains("Alexander")); }
     
    

Notez que nous utilisons notre identité de base comme:

x->true

Mais ce sera différent si nous voulons les combiner en utilisant Predicate.or () :

@Test public void whenFilterListWithCollectionOfPredicatesUsingOr_thenSuccess(){ List result = names.stream() .filter(allPredicates.stream().reduce(x->false, Predicate::or)) .collect(Collectors.toList()); assertEquals(2, result.size()); assertThat(result, contains("Adam","Alexander")); }

7. Conclusion

Dans cet article, nous avons exploré différentes façons de chaîner des prédicats dans Java 8, en utilisant filter (), en créant des prédicats complexes et en combinant des prédicats.

Le code source complet est disponible à l'adresse over sur GitHub.