Filtre de flux Java avec expression Lambda

Filtre de flux Java avec expression Lambda

1. introduction

Dans ce rapide tutoriel, nous allons explorer l'utilisation de la méthodeStream.filter() lorsque nous travaillons avecStreams in Java.

Nous allons montrer comment l'utiliser et comment gérer les cas spéciaux avec des exceptions cochées.

2. Utilisation deStream.filter()

La méthodefilter() est une opération intermédiaire de l'interfaceStream qui permet de filtrer les éléments d'un flux qui correspondent à unPredicate: donné

Stream filter(Predicate predicate)

Pour voir comment cela fonctionne, créons une classeCustomer:

public class Customer {
    private String name;
    private int points;
    //Constructor and standard getters
}

En outre, créons une collection de clients:

Customer john = new Customer("John P.", 15);
Customer sarah = new Customer("Sarah M.", 200);
Customer charles = new Customer("Charles B.", 150);
Customer mary = new Customer("Mary T.", 1);

List customers = Arrays.asList(john, sarah, charles, mary);

2.1. Filtrage des collections

Un cas d'utilisation courant de la méthodefilter() estprocessing collections.

Faisons une liste de clients avec plus de 100points. Pour ce faire, nous pouvons utiliser une expression lambda:

List customersWithMoreThan100Points = customers
  .stream()
  .filter(c -> c.getPoints() > 100)
  .collect(Collectors.toList());

Nous pouvons également utiliser unmethod reference, qui est un raccourci pour une expression lambda:

List customersWithMoreThan100Points = customers
  .stream()
  .filter(Customer::hasOverHundredPoints)
  .collect(Collectors.toList());

Mais, pour ce cas, nous avons ajouté la méthodehasOverHundredPoints à notre classeCustomer:

public boolean hasOverHundredPoints() {
    return this.points > 100;
}

Dans les deux cas, nous obtenons le même résultat:

assertThat(customersWithMoreThan100Points).hasSize(2);
assertThat(customersWithMoreThan100Points).contains(sarah, charles);

2.2. Filtrage des collections avec plusieurs critères

De plus, nous pouvons utiliser plusieurs conditions avecfilter(). Par exemple, filtrez parpoints etname:

List charlesWithMoreThan100Points = customers
  .stream()
  .filter(c -> c.getPoints() > 100 && c.getName().startsWith("Charles"))
  .collect(Collectors.toList());

assertThat(charlesWithMoreThan100Points).hasSize(1);
assertThat(charlesWithMoreThan100Points).contains(charles);

3. Gestion des exceptions

Jusqu'à présent, nous avons utilisé le filtre avec des prédicats qui ne lèvent pas d'exception. En effet lesfunctional interfaces in Java don’t declare any checked or unchecked exception.

Ensuite, nous allons montrer différentes manières de gérer lesexceptions in lambda expressions.

3.1. Utilisation d'un wrapper personnalisé

Tout d'abord, nous allons commencer à ajouter à nosCustomer aprofilePhotoUrl:

private String profilePhotoUrl;

De plus, ajoutons une méthodehasValidProfilePhoto() simple pour vérifier la disponibilité du profil:

public boolean hasValidProfilePhoto() throws IOException {
    URL url = new URL(this.profilePhotoUrl);
    HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
    return connection.getResponseCode() == HttpURLConnection.HTTP_OK;
}

Nous pouvons voir que la méthodehasValidProfilePhoto() lance unIOException. Maintenant, si nous essayons de filtrer les clients avec cette méthode:

List customersWithValidProfilePhoto = customers
  .stream()
  .filter(Customer::hasValidProfilePhoto)
  .collect(Collectors.toList());

Nous verrons l'erreur suivante:

Incompatible thrown types java.io.IOException in functional expression

Pour le gérer, une des alternatives que nous pouvons utiliser est de l'envelopper avec un bloc try-catch:

List customersWithValidProfilePhoto = customers
  .stream()
  .filter(c -> {
      try {
          return c.hasValidProfilePhoto();
      } catch (IOException e) {
          //handle exception
      }
      return false;
  })
  .collect(Collectors.toList());

Si nous avons besoin de lever une exception à partir de notre prédicat, nous pouvons l'envelopper dans une exception non vérifiée commeRuntimeException.

3.2. Utilisation deThrowingFunction

Alternativement, nous pouvons utiliser la bibliothèqueThrowingFunction.

ThrowingFunction est une bibliothèque open source qui nous permet de gérer les exceptions vérifiées dans les interfaces fonctionnelles Java.

Commençons par ajouter lesthrowing-function dependency à notre pom:


    pl.touk
    throwing-function
    1.3

Pour gérer les exceptions dans les prédicats, cette bibliothèque nous offre la classeThrowingPredicate, qui a la méthodeunchecked() pour encapsuler les exceptions vérifiées.

Voyons cela en action:

List customersWithValidProfilePhoto = customers
  .stream()
  .filter(ThrowingPredicate.unchecked(Customer::hasValidProfilePhoto))
  .collect(Collectors.toList());

4. Conclusion

Dans cet article, nous avons vu un exemple d'utilisation de la méthodefilter() pour traiter les flux. Nous avons également exploré certaines alternatives pour gérer les exceptions.

Comme toujours, le code complet est disponibleover on GitHub.