Tutoriel pour découvrir l’API Collections de Google Guava

La classe Collections2

Rony Rauzduel

L'objectif de ce cinquième article sur l’exploration de la bibliothèque Guava de Google est de vous présenter les méthodes statiques composant la classe utilitaire Collections2.

Cet article nous permettra d’apprécier toute la richesse de cette bibliothèque qui ne fait que s’améliorer au fur et à mesure des versions.

Lors de l’écriture de cet article, j’ai utilisé la version 30.1.1 de Google Guava.

Ce tutoriel est avant tout pratique, mon fil conducteur est la page suivante https://github.com/google/guava/wiki/ImmutableCollectionsExplainedained traitant des collections de l'API Google Guava.

Vous pouvez également consulter mes précédents tutoriels pour découvrir la bibliothèque Guava.

La classe Lists

La classe ImmutableList

La classe Iterables

La classe Sets

Pour réagir au contenu de cet article, un espace de dialogue vous est proposé sur le forum. Commentez

- Titre : Tutoriel pour découvrir l’API Collections de Google Guava

- Auteur : Rony Rauzduel

- Parution : 17 janvier 2022

- Public visé :

- Licence : Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright ® 2022 Rauzduel Rony. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.

Sommaire

- I. Introduction

- II. Ajouter Google Guava à votre projet (Rappel)

- III. La classe utilitaire Collections2

- IV. Implémentation des méthodes de la classe Collections2

- IV-A. Les imports

- IV-B. Les attributs, les blocs et les méthodes statiques

- IV-C. La méthode filter

- IV-D. La méthode orderedPermutations

- IV-D-1. orderedPermutations(Iterable<E> elements)

- IV-D-2. orderedPermutations(Iterable<E> elements, Comparator<? super E> comparator)

- IV-E. La méthode permutations

- IV-F. La méthode transform

- V. Conclusion

- VI. Remerciements

I - Introduction

Sans conteste, la meilleure manière de découvrir une bibliothèque est de parcourir chacune de ses méthodes et de les implémenter les unes après les autres pour comprendre les subtilités de chacune.

Ce tutoriel sur l’exploration de la bibliothèque Guava de Google reprend l’ensemble des méthodes statiques composant la classe utilitaire Collections2. Bonne lecture à tous.

II - Ajouter Google Guava à votre projet (Rappel)

La bibliothèque Google Guava peut être ajoutée de plusieurs façons dans un projet. La façon la plus triviale est de récupérer le .jar depuis le site de Google, puis de le placer directement dans la bibliothèque de votre projet.

Une autre façon plus élégante est d’utiliser un outil industrialisé de build comme Apache Maven ou Gradle en y ajoutant la dépendance requise de Google Guava.

Installer Guava avec Maven

1. <!-- https://mvnrepository.com/artifact/com.google.guava/guava -->

2. <dependency>

3. <groupId>com.google.guava</groupId>

4. <artifactId>guava</artifactId>

5. <version>30.1-jre</version>

6. </dependency>

III - La classe utilitaire Collections2

Force est de constater que tout développeur familier avec le langage Java connaît l’utilité pratique de l’API Collections.

Google Guava est allé encore plus loin dans l’implémentation des fonctionnalités sous-jacentes à l’utilisation des objets itérables. Les développeurs de Google ont conçu de nombreuses méthodes utilitaires statiques permettant une gestion efficiente lorsqu’on travaille avec des objets sur lesquels on peut itérer.

Mieux qu’un long discours dans le chapitre suivant, nous mettrons en œuvre la richesse de cette bibliothèque à travers un cas pratique de gestion d’un parc automobile.

IV - Implémentation des méthodes de la classe Collections2

IV-A - Les imports

Les imports

1. import com.google.common.collect.Collections2;

2. import static java.lang.System.out;

3. import java.util.ArrayList;

4. import java.util.Arrays;

5. import java.util.Collection;

6. import java.util.Comparator;

7. import java.util.HashSet;

8. import java.util.List;

9. import java.util.Stack;

10. import java.util.function.Function;

11. import java.util.function.Predicate;

IV-B - Les attributs, les blocs et les méthodes statiques

Les attributs, les blocs et les méthodes statiques

1. public final class Application {

3. private final static Collection<String> mitsubishi;

5. static { // les structures de données

6. mitsubishi = new Stack<>();

7. mitsubishi.add("Mitsubishi Space Star");

8. mitsubishi.add("Mitsubishi Outlander");

9. mitsubishi.add("Mitsubishi Outlander PHEV");

10. mitsubishi.add("Mitsubishi Eclipse Cross PHEV");

11. mitsubishi.add("Mitsubishi SUV ASX");

12. }

14. private final static Collection<String> audi;

16. static {

17. audi = new HashSet<>();

19. audi.add("Audi Nouvelle A8 L TFSI e");

20. audi.add("Audi A7 Sportback TFSI e");

21. audi.add("Audi A6 Berline TFSI");

22. audi.add("Audi A5 Sportback");

23. audi.add("Audi A4 Berline");

24. audi.add("Audi Nouvelle A3 Sportback");

25. audi.add("Audi A1 Sportback");

26. }

28. final static Collection<Float> consommations;

30. static { // la consommation du litre/100km, on voit qu'elle est très élevée.

31. consommations = new ArrayList<>();

32. consommations.add(4.3f);

33. consommations.add(5.8f);

34. consommations.add(6.9f);

35. consommations.add(7.4f);

36. consommations.add(8.5f);

37. consommations.add(9.2f);

38. }

40. final static Iterable<String> iterableCarburants = Arrays.asList(new String[]{

41. "GPL", "Diesel", "GNV", "Hybride", "Biodiesel", "Electrique", "Essence Sans Plomb 95", "Essence Sans Plomb 98"

42. });

44. // predicate

45. private final static Predicate<String> typeOutlander = t -> t.contains("Outlander");

47. public static void main(String[] args) {

48. // commençons par afficher la liste des véhicules de la marque Mitsubishi

49. out.println(mitsubishi); // [Mitsubishi Space Star, Mitsubishi Outlander, Mitsubishi Outlander PHEV, Mitsubishi Eclipse Cross PHEV, Mitsubishi SUV ASX]

50. }

IV-C - La méthode filter

Cette méthode permet de renvoyer tous les éléments d’une collection répondant à un prédicat (condition déterministe) défini. Nous voulons restituer tous les véhicules de la marque Mitsubishi de type Outlander.

Méthode filter(Collection<E> unfiltered, Predicate<? super E> predicate)

1. Collection<String> filterMitsubishiOutlander = Collections2.filter(mitsubishi, typeOutlander::test);

2. out.println(filterMitsubishiOutlander); // [Mitsubishi Outlander, Mitsubishi Outlander PHEV]

IV-D - La méthode orderedPermutations

Cette méthode permet de renvoyer une collection immuable ordonnée de toutes les permutations de l'objet Iterable spécifié en paramètre.

IV-D-1 - orderedPermutations(Iterable<E> elements)

Nous souhaitons effectuer une permutation triée de tous nos carburants.

Méthode orderedPermutations(Iterable<E> elements)

1. out.println(iterableCarburants); // [GPL, Diesel, GNV, Hybride, Biodiesel, Electrique, Essence sans plomb 95, Essence sans plomb 98]

2. Collection<List<String>> orderedPermutationsCarburants = Collections2.orderedPermutations(iterableCarburants);

3. out.println(orderedPermutationsCarburants); // orderedPermutationCollection([Biodiesel, Diesel, Electrique, Essence sans plomb 95, Essence sans plomb 98, GNV, GPL, Hybride])

IV-D-2 - orderedPermutations(Iterable<E> elements, Comparator<? super E> comparator)

Cette méthode existe sous une autre signature ayant comme paramètres un objet de type Iterable et un objet de type Comparator. Ainsi, nous pouvons effectuer une permutation triée en fonction de la longueur du nom du carburant le plus long.

Méthode orderedPermutations(Iterable<E> elements, Comparator<? super E> comparator)

1. // nous voulons effectuer un tri permuté en fonction de la longueur du nom du carburant du plus long au plus court

2. final Comparator<String> comparator = (String o1, String o2) -> (o2.length() - o1.length());

3. Collection<List<String>> orderedPermutationsWithComparator = Collections2.orderedPermutations(iterableCarburants, comparator);

4. out.println(orderedPermutationsWithComparator); // orderedPermutationCollection([Essence sans plomb 95, Essence sans plomb 98, Biodiesel, Electrique, Hybride, Diesel, GPL, GNV])

IV-E - La méthode permutations

Admettons que nous souhaitions restituer toutes les permutations d’un objet de type collection, la méthode permutations(Collection<E> elements) nous permet aisément d’effectuer cette opération. Effectuons cette opération sur les véhicules de la marque Audi.

Méthode permutations(Collection<E> elements)

1. audi.stream().forEach(System.out::println);

2. /* Audi A6 Berline TFSI

3. Audi A4 Berline

4. Audi A5 Sportback

5. Audi Nouvelle A8 L TFSI e

6. Audi A1 Sportback

7. Audi Nouvelle A3 Sportback

8. Audi A7 Sportback TFSI e */

9. Collection<List<String>> permutationsVehiculeAudi = Collections2.permutations(audi);

10. out.println(permutationsVehiculeAudi); // permutations([Audi A6 Berline TFSI, Audi A4 Berline, Audi A5 Sportback, Audi Nouvelle A8 L TFSI e, Audi A1 Sportback, Audi Nouvelle A3 Sportback, Audi A7 Sportback TFSI e])

IV-F - La méthode transform

Nous voulons désormais renvoyer une Collection sur laquelle une fonction a été appliquée sur chaque élément. La Collection renvoyée est une vue en direct de cette dernière suite à la transformation des éléments.

Méthode transform(Collection<F> fromCollection, Function<? super F,T> function)

1. // on a trouvé un procédé permettant de gagner 40% sur la consommation de nos véhicules mesurée en litres pour 100 km

2. final Function<Float, Float> multiplier = t -> t * 0.6f;

3. final Collection<Float> diminuerConsommation = Collections2.transform(consommations, multiplier::apply);

4. out.println(diminuerConsommation); // [2.5800002, 3.4800003, 4.1400003, 4.44, 5.1000004, 5.52]

V - Conclusion

Nous avons fait le tour des méthodes utilitaires présentes dans la classe Collections. Comme vous avez pu le constater, ces méthodes sont à la fois très simples d’utilisation et particulièrement efficaces. Je vous invite fortement à les implémenter dans vos projets, car elles vous apporteront des avantages sans précédent en termes de productivité.

Par ailleurs, je vous invite à créer un fil de discussion afin d’y laisser tous vos commentaires pour l’appréciation, voire pour l’amélioration des futurs tutoriels.

VI - Remerciements

Je remercie escartefigue pour la relecture orthographique de cet article, la communauté developpez.com qui propose un forum d’entraide d’une richesse fortement appréciable, Mickael Baron qui donne de son temps pour s’occuper de la rubrique Java, et surtout RomeoBeni pour l’écriture d’un ouvrage d’une rare simplicité dans l’apprentissage de la programmation en Java.

Pour finir merci encore à tous les membres répondant aux questions des débutants en programmation. Un grand merci à tous.