<?xml version="1.0" encoding="UTF-8"?>
<document>
	<!--XML créé avec la version 19.9 du KitOOoDVP le 30/01/2021 19:31:08-->
	<!--En-tête d'article-->
	<entete>
		<rubrique>1</rubrique>
		<meta>
			<description>Explorer l'API Collections de Google Guava s'interesse à la classe Lists https://guava.dev/releases/snapshot/...ect/Lists.html</description>
			<keywords/>
		</meta>
		<titre>
			<page>Exploration de la classe utilitaire Lists Google Guava</page>
			<article>Découvrir l’API Collections de Google Guava</article>
		</titre>
		<date>2021-01-30</date>
		<miseajour/>
		<extratag/>
		<google-analytics/>
		<licauteur>RAUZDUEL Rony</licauteur>
		<lictype>2</lictype>
		<licannee>2021</licannee>
		<serveur>transact-http</serveur>
		<chemin>guava/lists</chemin>
		<urlhttp>https://transact.developpez.com/guava/lists/</urlhttp>
		<pdf>
			<sautDePageAvantSection>0</sautDePageAvantSection>
			<notesBasPage>FinDocument</notesBasPage>
		</pdf>
		<microsofttraduction/>
	</entete>
	<!--Descriptions des auteurs-->
	<authorDescriptions>
		<authorDescription name="Transact" role="auteur">
			<fullname>RAUZDUEL Rony</fullname>
		</authorDescription>
	</authorDescriptions>
	<soustitre>La classe Lists</soustitre>
	<summary>
		<section id="I">
			<title>Introduction</title>
			<paragraph>Dans ce premier tutoriel sur l’exploration de la bibliothèque Guava de Google, nous allons parcourir les différentes méthodes les unes après les autres afin de découvrir les fonctionnalités de chacune et ainsi comment les exploiter de façon efficiente dans nos futurs projets. Ce tutoriel est le premier d’une longue série à venir. Dans ce premier volet nous découvrirons l’ensemble des méthodes statiques composant la classe utilitaire Lists. </paragraph>
			<paragraph>Par ailleurs comme il s'agit d'une découverte, je parcours la bibliothèque des méthodes de la classe Lists en y greffant des exemples simples. Fort est de constater que la façon la plus triviale et adéquate de comprendre les fonctionnalités d’une classe utilitaire est d’implémenter chacune des ses méthodes à l’aide d’exemple. Ce tutoriel est avant tout pratique, mon fil conducteur est la page suivante <link href="https://www.developpez.net/forums/redirect-to/?redirect=https%3A%2F%2Fgithub.com%2Fgoogle%2Fguava%2Fwiki%2FCollectionUtilitiesExplained" target="_blank">https://github.com/google/guava/wiki...itiesExplained</link> traitant des Collections de l'API Google Guava. Le lecteur devra donc s’attendre à voir la mise en œuvre des méthodes de la classe Lists de façon pragmatique et ludique. Souhaitant au lecteur d’apprécier toute la richesse de cette bibliothèque qui ne fait que s’améliorer au fur et à mesure des versions. Bonne lecture à tous.</paragraph>
		</section>
		<section id="II">
			<title>Qu’est-ce que l’API Google Guava et pourquoi l’utiliser ?</title>
			<paragraph>L’API Collections de Google Guava est une bibliothèque contenant un ensemble de classes utilitaires fort utiles dans n’importe quel projet Java. En effet, cette API contient des classes allant du traitement des collections permettant de gérer des objets immuables, à la manipulation des chaînes de caractères, en passant par la gestion des entrées-sorties conversationnelles, et bien d’autres fonctionnalités qui facilitent la vie du développeur. </paragraph>
			<paragraph>Dans cette série de tutoriels nous n’aborderons que les classes utilitaires de l’API Collections. Cette dernière regroupe un ensemble de classes analogues à celles présente dans le JDK mais  à la différence que ces dernières ont été améliorées par rapport à celles du JDK d’ORACLE.</paragraph>
			<paragraph>En effet les développeurs de Google ont souhaité étendre les fonctionnalités des structures de données natives que nous utilisons au quotidien afin d’accroître notre productivité.</paragraph>
			<paragraph>Le projet Guava représente le cœur du développement de Google, il représente des années de développement et une boîte à outils utilisée au quotidien par les développeurs de Google. Cette API est arrivée à maturité puisqu’elle est à l’heure actuelle à sa version 30.1 et ne cesse d’être agrémentée de nouvelles fonctionnalités.</paragraph>
			<paragraph>Sans conteste la meilleure manière de découvrir une bibliothèque est de parcourir chacune de ces méthodes et de les implémenter les unes après les autres pour comprendre les subtilités de chacune. </paragraph>
		</section>
		<section id="III">
			<title>Ajouter Google Guava à votre projet</title>
			<paragraph>La bibliothèque Google Guava peut être ajoutée de plusieurs façon dans un projet. La façon la plus triviale est de récupérer le .jar directement sur le site de Google puis de le placer directement dans les bibliothèques de votre projet.</paragraph>
			<paragraph>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.</paragraph>
			<code langage="xml" titre="Installer Guava via Maven"><![CDATA[<!-- https://mvnrepository.com/artifact/com.google.guava/guava -->
<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>30.1-jre</version>
</dependency>]]></code>
		</section>
		<section id="IV">
			<title>La classe utilitaire Lists</title>
			<paragraph>Comme je l’ai souligné tout développeur familier avec le langage Java connaît l’utilité pratique des structures de données implémentant l’interface java.util.Collections (List, Map, Set, etc.).</paragraph>
			<paragraph>Google Guava est allé encore plus loin dans l’implémentation des fonctionnalités sous-jacente à l’utilisation de ces structures de données. Les développeurs de Google ont conçus de nombreuses méthodes utilitaires statiques permettant une gestion efficiente lorsque l’on travaille avec des objets de type List.</paragraph>
			<paragraph>La classe com.google.common.collect.Lists contient des méthodes statiques utilitaires permettant de créer des instances de l'interface List du JDK.</paragraph>
			<paragraph>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.</paragraph>
		</section>
		<section id="V">
			<title>Implémentation des méthodes de la classe Lists</title>
			<section id="V-A">
				<title>Les imports</title>
				<code langage="java" titre="Les imports"><![CDATA[import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import static java.lang.System.out;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.function.Function;]]></code>
				<section id="V-A-1">
					<title>Les attributs et blocs statiques</title>
					<paragraph>Créons une classe Application qui contiendra les attributs, les blocs et les méthodes statiques  pour la gestion de notre parc automobile.</paragraph>
					<code langage="java" titre="les attributs et blocs statiques"><![CDATA[public final class Application {
    private final static int NB_MARQUES_VEHICULES = 5;
    private final static String[] peugeot;
    private final static String[] toyota;
    private final static String[] opel;
    private final static String[] renault;
    private final static String[] citroen;
    private final static List<String> carburants; // types de carburants
    private final static List<Float> consommations;

    static { // les marques des véhicules
        peugeot = new String[NB_MARQUES_VEHICULES];
        peugeot[0] = "Peugeot Nouvelle SUV 3008";
        peugeot[1] = "Peugeot Nouvelle SUV 5008";
        peugeot[2] = "Peugeot Traveller/Expert Combi";
        peugeot[3] = "Peugeot Boxer";
        peugeot[4] = "Peugeot Tepee";

        toyota = new String[NB_MARQUES_VEHICULES];
        toyota[0] = "Toyota Auris";
        toyota[1] = "Toyota Nouvelle Yaris";
        toyota[2] = "Toyota Aygo X ";
        toyota[3] = "Toyota Prius+";
        toyota[4] = "Toyota Nouvelle C-HR";

        opel = new String[NB_MARQUES_VEHICULES];
        opel[0] = "Opel Calibra";
        opel[1] = "Opel Ascona";
        opel[2] = "Opel Corsa";
        opel[3] = "Opel Alambra";
        opel[4] = "Opel Meriva";

        renault = new String[NB_MARQUES_VEHICULES];
        renault[0] = "Renault Kangoo VP";
        renault[1] = "Renault Nouveau Grand Scenic";
        renault[2] = "Renault Alaskan";
        renault[3] = "Talisman Estate";
        renault[4] = "Renault Safrane";

        citroen = new String[NB_MARQUES_VEHICULES];
        citroen[0] = "Citroen Nouvelle C-Elysée";
        citroen[1] = "Citroen Nemo Multispace";
        citroen[2] = "Citroen C4 Aircross";
        citroen[3] = "Citroen Nouveau Grand C4 Picasso";
        citroen[4] = "Citroen Space Tourer Business Lounge";
    }
    
    static { // les types de carburants
        carburants = new ArrayList<>();
        carburants.add("Essence");
        carburants.add("Diesel");
        carburants.add("GNV"); // Gaz naturel pour véhicules
        carburants.add("Hybride");
        carburants.add("Biodiesel");
        carburants.add("Electric");
    }

    static { // la consommation du litre/100km, on voit qu'elle est très élevée.
        consommations = new ArrayList<>();
        consommations.add(4.3f);
        consommations.add(5.8f);
        consommations.add(6.9f);
        consommations.add(7.4f);
        consommations.add(8.5f);
        consommations.add(9.2f);
    }

    public static void main(String[] args) {
        // commençons par afficher la liste des véhicules de la marque Peugeot
        out.println(Arrays.asList(peugeot)); // [Peugeot Nouvelle SUV 3008, Peugeot Nouvelle SUV 5008, Peugeot Traveller/Expert Combi, Peugeot Boxer, Peugeot Tepee]
    }    
}]]></code>
				</section>
			</section>
			<section id="V-B">
				<title>La méthode asList</title>
				<section id="V-B-1">
					<title>asList(E first, E[] rest)</title>
					<paragraph>Ajoutons un nouveau véhicule au début de notre liste en utilisant la méthode asList(E first, E[] rest) puis affichons cette liste de véhicules. On constate que le véhicule a été ajouté au tout début de la liste.</paragraph>
					<code langage="java" titre="Méthode asList(E first, E[] rest)"><![CDATA[final List<String> peugeotImmutableList = Lists.asList("Peugeot 107", peugeot);
peugeotImmutableList.forEach(System.out::println);
/*
Peugeot 107
Peugeot Nouvelle SUV 3008
Peugeot Nouvelle SUV 5008
Peugeot Traveller/Expert Combi
Peugeot Boxer
Peugeot Tepee
*/]]></code>
					<paragraph>A noter que la liste étant immuable donc si vous essayez d'ajouter un autre véhicule par la suite une exception sera levée.</paragraph>
					<code langage="java" titre="UnsupportedOperationException"><![CDATA[peugeotImmutableList.add("Peugeot 107");]]></code>
				</section>
				<section id="V-B-2">
					<title>asList(E first, E second, E[] rest)</title>
					<paragraph>Dans ce cas de figure, il est préférable d’utiliser la méthode asList(E first, E second, E[] rest).</paragraph>
					<code langage="java" titre="Méthode asList(E first, E second, E[] rest)"><![CDATA[final List<String> peugeotOtherImmutableList = Lists.asList("Peugeot 107", "Peugeot 108", peugeot);
peugeotOtherImmutableList.forEach(System.out::println);
/*
Peugeot 107
Peugeot 108
Peugeot Nouvelle SUV 3008
Peugeot Nouvelle SUV 5008
Peugeot Traveller/Expert Combi
Peugeot Boxer
Peugeot Tepee
*/]]></code>
				</section>
			</section>
			<section id="V-C">
				<title>La méthode cartesianProduct</title>
				<paragraph>Nous souhaitons maintenant récupérer le produit cartésien, c’est-à-dire l’ensemble des types de carburants disponibles pour les véhicules de la marque Peugeot. Par ailleurs cette méthode possède 2 variantes dont l’une prend en compte un argument variable de type List au lieu d’une unique List.</paragraph>
				<section id="V-C-1">
					<title>cartesianProduct(List&lt;? extends B> …lists)</title>
					<paragraph>Pour effectuer cette tâche de récupération des types de carburants, nous pouvons directement utiliser la deuxième variante de la méthode cartesianProduct(List&lt;? extends B> …lists).</paragraph>
					<code langage="java" titre="Méthode cartesianProduct(List&lt;? extends List&lt;? extends B>> ...lists)"><![CDATA[List<List<String>> immutableCartesianProduct = Lists.cartesianProduct(peugeotImmutableList, carburants);
out.println(immutableCartesianProduct);
/*
[[Peugeot 108, Essence], [Peugeot 108, Diesel], [Peugeot 108, GNV], [Peugeot 108, Hybride], [Peugeot 108, Biodiesel], [Peugeot 108, Electric], [Peugeot Nouvelle SUV 3008, Essence], [Peugeot Nouvelle SUV 3008, Diesel], [Peugeot Nouvelle SUV 3008, GNV], [Peugeot Nouvelle SUV 3008, Hybride], [Peugeot Nouvelle SUV 3008, Biodiesel], [Peugeot Nouvelle SUV 3008, Electric], [Peugeot Nouvelle SUV 5008, Essence], [Peugeot Nouvelle SUV 5008, Diesel], [Peugeot Nouvelle SUV 5008, GNV], [Peugeot Nouvelle SUV 5008, Hybride], [Peugeot Nouvelle SUV 5008, Biodiesel], [Peugeot Nouvelle SUV 5008, Electric], [Peugeot Traveller/Expert Combi, Essence], [Peugeot Traveller/Expert Combi, Diesel], [Peugeot Traveller/Expert Combi, GNV], [Peugeot Traveller/Expert Combi, Hybride], [Peugeot Traveller/Expert Combi, Biodiesel], [Peugeot Traveller/Expert Combi, Electric], [Peugeot Boxer, Essence], [Peugeot Boxer, Diesel], [Peugeot Boxer, GNV], [Peugeot Boxer, Hybride], [Peugeot Boxer, Biodiesel], [Peugeot Boxer, Electric], [Peugeot Tepee, Essence], [Peugeot Tepee, Diesel], [Peugeot Tepee, GNV], [Peugeot Tepee, Hybride], [Peugeot Tepee, Biodiesel], [Peugeot Tepee, Electric]]
*/]]></code>
				</section>
				<section id="V-C-2">
					<title>cartesianProduct(List&lt;? extends List&lt;? extends B>> lists)</title>
					<paragraph>Soit nous pouvons utiliser une boucle pour parcourir les couples formés par le produit cartésien souhaité [véhicule, carburant].</paragraph>
					<code langage="java" titre="Méthode cartesianProduct(List&lt;? extends List&lt;? extends B>> lists)"><![CDATA[peugeotImmutableList.forEach(vehicule -> {
            carburants.stream()
                    //.filter(carburant -> carburant.equals("Diesel")) // si on souhaite uniquement les véhicules "Diesel"
                    .map(carburant -> ImmutableList.of(vehicule, carburant))
                    .forEachOrdered(couple -> {
                        out.println(couple);
                    });
        });]]></code>
				</section>
			</section>
			<section id="V-D">
				<title>La méthode charactersOf</title>
				<paragraph>Maintenant nous souhaitons récupérer indépendamment chaque caractère d’une séquence de caractère d’un véhicule de la marque Peugeot.</paragraph>
				<section id="V-D-1">
					<title>charactersOf(CharSequence sequence)</title>
					<code langage="java" titre="Méthode charactersOf(CharSequence sequence)"><![CDATA[final CharSequence vehiculePeugeot4008 = "Peugeot 4008";
final List<Character> peugeot4008 = Lists.charactersOf(vehiculePeugeot4008);
out.println(peugeot4008); // [P, e, u, g, e, o, t,  , 4, 0, 0, 8]]]></code>
					<paragraph>Comme il ne s’agit que d’une vue de la séquence de caractères, cette dernière n’est accessible qu’en lecture-seule. Par contre toute modification de la séquence de caractères initiale entraîne une modification de la vue.</paragraph>
					<code langage="java" titre="UnsupportedOperationException "><![CDATA[peugeot4008.remove(7); // UnsupportedOperationException]]></code>
				</section>
				<section id="V-D-2">
					<title>charactersOf(String string)</title>
					<paragraph>Nous pouvons effectuer la même opération pour récupérer indépendamment chaque caractère mais cette fois-ci d’une chaîne de caractère d’un véhicule de la marque Peugeot. Par contre avec cette redéfinition de la méthode la liste renvoyée est directement immuable.</paragraph>
					<code langage="java" titre="Méthode ImmutableList&lt;Character> charactersOf(String string)"><![CDATA[final ImmutableList<Character> vehiculePeugeot5008 = Lists.charactersOf("Peugeot 5008");
out.println(vehiculePeugeot5008); // [P, e, u, g, e, o, t,  , 5, 0, 0, 8]]]></code>
				</section>
			</section>
			<section id="V-E">
				<title>La méthode newArrayList</title>
				<paragraph>Nous voulons cette fois-ci instancier un type ArrayList mutable comme nous le faisons lorsque nous utilisons cette structure de données. Mais avec l’API de Google Guava cela se fait différemment.</paragraph>
				<section id="V-E-1">
					<title>newArrayList()</title>
					<code langage="java" titre="Méthode ArrayList&lt;E> newArrayList()"><![CDATA[final ArrayList<String> vehiculeMutableArrayList = Lists.newArrayList(); // une ArrayList mutable …
vehiculeMutableArrayList.add("Peugeot 207"); // à laquelle on ajoute un véhicule Peugeot
vehiculeMutableArrayList.add("Renault Velsatis"); // puis un véhicule Renault
vehiculeMutableArrayList.add("Citroen Saxo"); // puis un véhicule Renault
out.println(vehiculeMutableArrayList);
// [Peugeot 207, Renault Velsatis, Citroen Saxo]]]></code>
				</section>
				<section id="V-E-2">
					<title>newArrayList(E… elements)</title>
					<paragraph>Cette méthode possède également une autre variante prenant comme paramètre une ellipse ; cette variante quant à elle nous permets de créer une ArrayList directement avec nos véhicules.</paragraph>
					<code langage="java" titre="Méthode ArrayList&lt;E> newArrayList(E... elements)"><![CDATA[final ArrayList<String> toyotaMutableArrayList = Lists.newArrayList("Toyota Starlet", "Toyota Nouvelle Starlet"); // une liste mutable initialisée avec des véhicules Toyota 
toyotaMutableArrayList.add("Toyota Nouvelle Starlet+"); // à laquelle on ajoute un nouveau véhicule Toyota
out.println(toyotaMutableArrayList);
// [Toyota Starlet, Toyota Nouvelle Starlet, Toyota Nouvelle Starlet+]]]></code>
				</section>
			</section>
			<section id="V-F">
				<title>La méthode LinkedList</title>
				<paragraph>idem avec pour un objet de type LinkedList</paragraph>
				<code langage="java" titre="Méthode LinkedList&lt;E> newLinkedList()"><![CDATA[final LinkedList<String> vehiculeMutableLinkedList = Lists.newLinkedList();  // une LinkedList mutable ...
vehiculeMutableLinkedList.add("Opel Zafira Life"); // à laquelle on ajoute un véhicule Opel
vehiculeMutableLinkedList.add("Citroen DS 7 Crossback"); // à laquelle on ajoute un véhicule Citroen
vehiculeMutableLinkedList.add("Renault Koléos"); // à laquelle on ajoute un véhicule Renault
out.println(vehiculeMutableLinkedList);
// [Opel Zafira Life, Citroen DS 7 Crossback, Renault Koléos]]]></code>
				<code langage="java" titre="Méthode LinkedList&lt;E> newLinkedList(E... elements)"><![CDATA[final LinkedList<String> opelMutableLinkedList = Lists.newLinkedList(Arrays.asList(opel));
opelMutableLinkedList.add("Opel Insignia Grand Sport");
out.println(opelMutableLinkedList);
// [Opel Calibra, Opel Ascona, Opel Corsa, Opel Alambra, Opel Meriva, Opel Insignia Grand Sport]]]></code>
			</section>
			<section id="V-G">
				<title>La méthode partition(List&lt;T> list, int size)</title>
				<paragraph>L’API Google Guava nous permets également de partitionner (sectionner en sous-liste) notre liste de véhicules en choisissant la longueur de chacune des sous-listes. A noter que si tous les éléments ne peuvent pas être mis dans une sous-liste de longueur définie alors ils se retrouvent dans une sous-liste de longueur inférieure à celle définie à l’origine.</paragraph>
				<code langage="java" titre="Méthode List&lt;List&lt;T>> partition(List&lt;T> list, int size)"><![CDATA[final List<List<String>> citroenListCarburants = Lists.partition(carburants, 5);
out.println(citroenListCarburants);
List<String> subList = Arrays.asList(citroen).subList(1, 3);
out.println(subList);
// [[Essence, Diesel, GNV, Hybride, Biodiesel], [Electric]]
// [Diesel, GNV]]]></code>
			</section>
			<section id="V-H">
				<title>La méthode reverse(List&lt;T> list)</title>
				<paragraph>Désormais nous voulons restituer notre liste de véhicules dans l’ordre inverse d’insertion.</paragraph>
				<code langage="java" titre="Méthode List&lt;T> reverse(List&lt;T> list)"><![CDATA[out.println(Arrays.asList(toyota));
final List<String> toyotaReverseList = Lists.reverse(Arrays.asList(toyota));
out.println(toyotaReverseList);
// [Toyota Auris, Toyota Nouvelle Yaris, Toyota Aygo X , Toyota Prius+, Toyota Nouvelle C-HR]
// [Toyota Nouvelle C-HR, Toyota Prius+, Toyota Aygo X , Toyota Nouvelle Yaris, Toyota Auris]]]></code>
			</section>
			<section id="V-I">
				<title>La méthode transform(List&lt;F> fromList, Function&lt;? super F,? extends T> function)</title>
				<paragraph>Nous pouvons également transformer les éléments de notre liste en leur appliquant une fonction de « transformation » prédéfinie. </paragraph>
				<paragraph>Nous avons trouvé un procédé permettant de gagner 40% sur la consommation du litre au 100km de nos véhicules.</paragraph>
				<code langage="java" titre="Méthode &lt;F,T> List&lt;T> transform(List&lt;F> fromList, Function&lt;? super F,? extends T> function)"><![CDATA[final Function<Float, Float> multiplier = t -> t * 0.6f;
// To use a java.util.function.Function in a context where a com.google.common.base.Function is needed, use function::apply. 
// donc on peut utiliser directement la méthode de référence (sans argument) apply
final List<Float> diminuerConsommation = Lists.transform(consommations, multiplier::apply);
out.println(diminuerConsommation); // 1.5600000381469727
// ou directement avec la classe String de l'API Java
final List<String> carburantsToUppercase = Lists.transform(carburants, String::toUpperCase);
out.println(carburantsToUppercase); 
// [2.5800002, 3.4800003, 4.1400003, 4.44, 5.1000004, 5.52]
// [ESSENCE, DIESEL, GNV, HYBRIDE, BIODIESEL, ELECTRIC]]]></code>
			</section>
		</section>
		<section id="VI">
			<title>Résumé</title>
			<paragraph>Nous avons fait le tour des méthodes utilitaires présentes dans la classe Lists. Comme vous avez pu le constater ces méthodes sont à la fois très simple d’utilisation et particulièrement efficace. Je vous invite fortement à les implémenter dans vos projets car elles vous apporteront des avantages sans précédent en terme de productivité. </paragraph>
			<paragraph>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.</paragraph>
		</section>
		<section id="VII">
			<title>Remerciements</title>
			<paragraph>Je tiens à remercier tout particulièrement les membres de la communauté developpez.com qui propose un forum d’entraide d’une richesse fortement appréciable. Je remercie Mickael Baron qui donne de son temps pour s’occuper de la rubrique Java, RomeoBeni que je remercie d’avoir écrit une ouvrage d’une rare simplicité pour apprendre à programmer en Java, mais aussi à tous les membres répondant aux questions des débutants en programmation dont je faisais partie il y a quelques années de cela. Merci à tous.</paragraph>
		</section>
	</summary>
</document>
