Chaîne de prédicats Java 8

Chaîne de prédicats Java 8

1. Vue d'ensemble

Dans ce tutoriel rapide,we’ll discuss different ways to chain Predicates in Java 8.

2. Exemple de base

Tout d'abord,let’s see how to use a simple Predicate pour filtrer unList 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é nosList de noms pour ne laisser que les noms commençant par «A» en utilisant lesPredicate:

name -> name.startsWith("A")

Mais que faire si nous voulions appliquer plusieursPredicates?

3. Filtres multiples

Si nous voulions appliquer plusieursPredicates,one option is to simply chain multiple filters:

@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 commençant par "A" et ayant une longueur inférieure à 5.

Nous avons utilisé deux filtres - un pour chaquePredicate.

4. ComplexePredicate

Maintenant, au lieu d'utiliser plusieurs filtres,we can use one filter with a complex Predicate:

@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, carwe can use bitwise operations to build the Predicate est aussi complexe que nous le voulons.

5. Combinaison dePredicates

Ensuite, si nous ne voulons pas construire unPredicate complexe en utilisant des opérations au niveau du bit, Java 8Predicate a des méthodes utiles que nous pouvons utiliser pour combinerPredicates.

Nous allons combinerPredicates en utilisant les méthodesPredicate.and(),Predicate.or() etPredicate.negate().

5.1. Predicate.and()

Dans cet exemple, nous définirons explicitement nosPredicates, puis nous les combinerons en utilisantPredicate.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 constater, la syntaxe est assez intuitive et les noms de méthodes suggèrent le type d'opération. En utilisantand(), nous avons filtré nosList en extrayant uniquement les noms qui remplissent les deux conditions.

5.2. Predicate.or()

On peut aussi utiliserPredicate.or() pour combinerPredicates.

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 utiliserPredicate.negate() lors de la combinaison de nosPredicates:

@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 deor() etnegate() pour filtrer lesList par des noms commençant par «J» ou ayant une longueur qui n’est pas inférieure à 4.

5.4. CombinerPredicates en ligne

Nous n'avons pas besoin de définir explicitement nosPredicates pour utiliserand(),or() etnegate().

Nous pouvons également les utiliser en ligne en castant lesPredicate:

@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 dePredicates

Enfin,let’s see how to chain a collection of Predicates by reducing them.

Dans l'exemple suivant, nous avons unList dePredicates que nous avons combiné en utilisantPredicate.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 utilisantPredicate.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 manières de chaîner des prédicats dans Java 8, en utilisantfilter(), pour construire des complexesPredicates et en combinantPredicates.

Le code source complet est disponibleover on GitHub.