Filtre de flux Java avec expression Lambda

1. Introduction

Dans ce rapide tutoriel, nous explorerons l'utilisation de la méthode Stream.filter () lorsque nous travaillons avec Streams en Java.

Nous verrons comment l'utiliser et comment gérer les cas spéciaux avec des exceptions vérifiées.

2. Utilisation de Stream.filter ()

La méthode filter () est une opération intermédiaire de l' interface Stream qui nous permet de filtrer les éléments d'un flux qui correspondent à un prédicat donné :

Stream filter(Predicate predicate)

Pour voir comment cela fonctionne, créons une classe Customer :

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

De plus, 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éthode filter () est le traitement des collections.

Faisons une liste de clients avec plus de 100 points. 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 une référence de méthode, qui est un raccourci pour une expression lambda:

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

Dans ce cas, nous avons ajouté la méthode hasOverHundredPoints à notre classe Customer :

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

Dans les deux cas, on obtient 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 avec filter () . Par exemple, nous pouvons filtrer par points et par nom :

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, les interfaces fonctionnelles en Java ne déclarent aucune exception cochée ou non cochée .

Ensuite, nous allons montrer différentes manières de gérer les exceptions dans les expressions lambda.

3.1. Utilisation d'un wrapper personnalisé

Tout d'abord, nous allons commencer par ajouter un profilePhotoUrl à notre client :

private String profilePhotoUrl;

De plus, ajoutons une simple méthode hasValidProfilePhoto () 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éthode hasValidProfilePhoto () lève une IOException . 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, l'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 devons lever une exception à partir de notre prédicat, nous pouvons l' encapsuler dans une exception non vérifiée comme RuntimeException .

3.2. Utilisation de ThrowingFunction

Alternativement, nous pouvons utiliser la bibliothèque ThrowingFunction.

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 la dépendance throwing-function à notre pom:

 pl.touk throwing-function 1.3 

Pour gérer les exceptions dans les prédicats, cette bibliothèque nous offre la classe ThrowingPredicate , qui a la méthode unchecked () 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éthode filter () pour traiter les flux. Nous avons également exploré quelques alternatives pour gérer les exceptions.

Comme toujours, le code complet est disponible à l'adresse over sur GitHub.