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 reprends l’ensemble des méthodes statiques composant la classe utilitaire Iterables.
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 placer ce dernier 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.
2.
3.
4.
5.
6.
<!-- https://mvnrepository.com/artifact/com.google.guava/guava -->
<dependency>
<groupId>
com.google.guava</groupId>
<artifactId>
guava</artifactId>
<version>
30.1-jre</version>
</dependency>
III. La classe utilitaire Iterables▲
Force est de constater que tout développeur familier avec le langage Java connaît l’utilité de pouvoir parcourir des implémentations (notamment List et Set) de manière uniforme sans devoir se soucier des mécanismes internes.
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 lorsque l’on travaille avec des objets sur lesquels on puisse 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 Iterables▲
IV-A. Les imports▲
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
import
com.google.common.collect.ImmutableList;
import
com.google.common.collect.Iterables;
import
static
java.lang.System.out;
import
java.util.ArrayList;
import
java.util.Arrays;
import
java.util.Collection;
import
java.util.Comparator;
import
java.util.Iterator;
import
java.util.LinkedList;
import
java.util.List;
import
java.util.Optional;
import
java.util.Queue;
import
java.util.function.Function;
import
java.util.function.Predicate;
IV-B. Les attributs, les blocs et les méthodes statiques▲
Créons une classe Application qui contiendra les attributs, les blocs et les méthodes statiques pour la gestion de notre parc automobile.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
public
final
class
Application {
// constantes
private
final
static
int
NB_MARQUES_VEHICULES =
5
;
private
final
static
int
NB_PEINTURES_VEHICULES =
5
;
private
final
static
int
NB_VEHICULES =
3
;
// predicates
private
final
static
Predicate<
String>
marquePeugeot;
private
final
static
Predicate<
String>
marqueOpel;
private
final
static
Predicate<
String>
marqueRenault;
private
final
static
Predicate<
String>
marqueMitsubishi;
// structures de données
private
final
static
List<
String>
vehicules;
private
final
static
List<
Number>
consommations;
private
final
static
String[] peugeot;
private
final
static
String[] opel;
private
final
static
String[] peinture;
static
{
peugeot =
new
String[NB_VEHICULES];
peugeot[0
] =
"Peugeot Nouvelle SUV 3008"
;
peugeot[1
] =
"Peugeot Nouvelle SUV 5008"
;
peugeot[2
] =
"Peugeot Traveller/Expert Combi"
;
opel =
new
String[NB_VEHICULES];
opel[0
] =
"Opel Calibra"
;
opel[1
] =
"Opel Ascona"
;
opel[2
] =
"Opel Corsa"
;
peinture =
new
String[NB_PEINTURES_VEHICULES];
peinture[0
] =
"Gris Shark"
;
peinture[1
] =
"Gris Thorium"
;
peinture[2
] =
"Bourrasque"
;
peinture[3
] =
"Bleu Encre"
;
peinture[4
] =
"Noir Obsidien"
;
vehicules =
new
ArrayList<>(
NB_MARQUES_VEHICULES);
}
static
{
// la consommation du litre/100km
final
Byte deuxLitre100km =
2
;
final
Short troisLitre100km =
3
;
consommations =
new
ArrayList<>(
);
consommations.add
(
deuxLitre100km);
consommations.add
(
troisLitre100km);
consommations.add
(
4.3
d); // Double
consommations.add
(
5.8
f); // Float
consommations.add
(
6
); // Integer
consommations.add
(
7
L); // Long
consommations.add
(
8.5
f); // Float
consommations.add
(
9.2
d); // Double
consommations.add
(
9
); // Integer
consommations.add
(
9.7
d); // Double
consommations.add
(
10
L); // Long
}
static
{
// predicates
marquePeugeot =
v ->
v.contains
(
"Peugeot"
);
marqueOpel =
v ->
v.contains
(
"Opel"
);
marqueRenault =
v ->
v.contains
(
"Renault"
);
marqueMitsubishi =
v ->
v.contains
(
"Mitsubishi"
);
}
static
Iterable<
String>
iterableVehicules =
new
ArrayList<>(
NB_MARQUES_VEHICULES);
final
static
List<
String>
couleurs =
Arrays.asList
(
new
String[]{
"Blanc Banquise"
, "Rouge Lucifer"
, "Gris Graphite"
, "Gris Futura"
, "Bleu de Sevres"
,
"Noir Perla"
, "Gris Alluminium"
, "Rouge Aden"
, "Blanc Perle"
, "Bleu Lucia"
, "Gris Futura"
}
);
final
static
Iterable<
String>
iterableRenault
=
Arrays.asList
(
new
String[]{
"Renault Kangoo VP"
, "Renault Nouveau Grand Scenic"
, "Renault Alaskan"
}
);
final
static
Iterable<
String>
iterableCitroen
=
Arrays.asList
(
new
String[]{
"Citroen Nouvelle C-Elysée"
, "Citroen Nemo Multispace"
, "Citroen C4 Aircross"
}
);
final
static
Iterable<
String>
iterableToyota
=
Arrays.asList
(
new
String[]{
"Toyota Auris"
, "Toyota Nouvelle Yaris"
, "Toyota Aygo X "
}
);
final
static
Iterable<
Integer>
iterableDiametreJantes =
Arrays.asList
(
new
Integer[]{
13
, 14
, 15
, 16
, 17
, 18
}
);
public
static
void
main
(
String[] args) {
// commençons par afficher les véhicules de la marque peugeot
out.println
(
Arrays.asList
(
peugeot)); // [Peugeot Nouvelle SUV 3008, Peugeot Nouvelle SUV 5008, Peugeot Traveller/Expert Combi]
}
}
IV-C. La méthode addAll▲
Ajoutons l’ensemble de nos véhicules de la marque Peugeot dans notre collection de véhicules. La méthode addAll(Collection<T> addTo, Iterable<? extends T> elementsToAdd) nous permet d’effectuer cette action avec une valeur booléenne à true si la collection a été modifiée à l’issue de cette opération.
2.
final
boolean
addAllVehicules =
Iterables.addAll
(
vehicules, Arrays.asList
(
peugeot));
out.println
(
addAllVehicules); // true
IV-D. La méthode all▲
Nous aurions pu également ajouter à notre collection de véhicules uniquement les véhicules de la marque Peugeot. Admettons que ces derniers soient présents dans un ensemble de marques de véhicules distinctes. Pour cela la méthode all(Iterable<T> iterable, Predicate<? super T> predicate) est préférable, car elle prend comme second paramètre un Predicate. Si tous les éléments de la collection répondent à la condition du Predicate, alors la valeur booléenne true est restituée sinon false dans le cas contraire.
2.
3.
4.
5.
6.
// Attention : il s'agit du Predicate de Google Guava et pas celui du JDK !!!
// Predicate where a com.google.common.base.Predicate is expected, use the method reference predicate::test.
final
boolean
allMarquePeugeot =
Iterables.all
(
vehicules, marquePeugeot::test);
out.println
(
allMarquePeugeot); // true
vehicules.add
(
"Opel Calibra"
); // on ajoute un véhicule qui n'est pas de la marque Peugeot
out.println
(
Iterables.all
(
vehicules, marquePeugeot::test)); // false
IV-E. La méthode any▲
Maintenant, soyons moins restrictifs en recherchant dans notre collection de véhicules n’importe quel élément répondant à une condition bien précise. Pour cela la méthode any(Iterable<T> iterable, Predicate<? super T> predicate) nous permet d’effectuer cette action. Cette méthode renvoie la valeur true en cas de succès ou false dans le cas contraire.
2.
out.println
(
Iterables.any
(
vehicules, marqueOpel::test)); // true puisque nous avons ajouté précédemment un véhicule de la marque Opeml
out.println
(
Iterables.any
(
vehicules, marqueRenault::test)); // false car on n'a pas ajouté de vehicule de la marque Renault
IV-F. La méthode concat▲
Nous décidons tout compte fait de concaténer la liste de tous nos véhicules dans un Iterable. Pour cela le polymorphisme de la méthode concat() met à notre disposition un panel de possibilités.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
iterableVehicules =
Iterables.concat
(
iterableRenault);
out.println
(
iterableVehicules);
iterableVehicules =
Iterables.concat
(
iterableRenault, iterableCitroen);
out.println
(
iterableVehicules);
iterableVehicules =
Iterables.concat
(
iterableRenault, iterableCitroen, iterableToyota);
out.println
(
iterableVehicules);
iterableVehicules =
Iterables.concat
(
iterableRenault, iterableCitroen, iterableToyota, Arrays.asList
(
opel));
out.println
(
iterableVehicules);
/*
[Renault Kangoo VP, Renault Nouveau Grand Scenic, Renault Alaskan]
[Renault Kangoo VP, Renault Nouveau Grand Scenic, Renault Alaskan, Citroen Nouvelle C-Elysée, Citroen Nemo Multispace, Citroen C4 Aircross]
[Renault Kangoo VP, Renault Nouveau Grand Scenic, Renault Alaskan, Citroen Nouvelle C-Elysée, Citroen Nemo Multispace, Citroen C4 Aircross, Toyota Auris, Toyota Nouvelle Yaris, Toyota Aygo X ]
[Renault Kangoo VP, Renault Nouveau Grand Scenic, Renault Alaskan, Citroen Nouvelle C-Elysée, Citroen Nemo Multispace, Citroen C4 Aircross, Toyota Auris, Toyota Nouvelle Yaris, Toyota Aygo X , Opel Calibra, Opel Ascona, Opel Corsa]
*/
IV-G. La méthode consumingIterable▲
Nous voulons renvoyer les codes couleurs de nos véhicules sous la forme d’une vue parcourue par un objet de type Iterator. La méthode consumingIterable(Iterable<T> iterable) nous permet d’effectuer cette opération.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
final
Queue<
String>
queueCodesCouleurs =
new
LinkedList<>(
couleurs);
final
Iterator<
String>
iterator =
Iterables.consumingIterable
(
queueCodesCouleurs).iterator
(
);
int
index =
0
;
while
(
iterator.hasNext
(
) &&
index <
5
) {
// on ne veut afficher que les 5 premières couleurs
final
String couleur =
iterator.next
(
);
out.println
(
couleur);
index++
;
}
/*
Blanc Banquise
Rouge Lucifer
Gris Graphite
Gris Futura
Bleu de Sevres
*/
IV-H. La méthode contains▲
Nous désirons savoir si la couleur « Rouge Aden » est présente dans notre Iterable des couleurs. La méthode contains(Iterable<?> iterable, @Nullable Object element) renvoie la valeur true en cas de succès ou false dans le cas contraire.
2.
final
boolean
containsRougeAden =
Iterables.contains
(
couleurs, "Rouge Aden"
);
out.println
(
containsRougeAden); // true
IV-I. La méthode cycle▲
IV-I-1. cycle(Iterable<T> iterable)▲
Nous pouvons également effectuer le parcours de nos codes couleurs en utilisant la méthode cycle(Iterable<T> iterable). Cependant si vous utilisez cette méthode dans une boucle, vous devrez explicitement ajouter le mot-clé break sinon le résultat produira une boucle infinie.
2.
3.
final
Iterable<
String>
iterableCouleurs =
Iterables.cycle
(
couleurs);
out.println
(
iterableCouleurs);
// [Blanc Banquise, Rouge Lucifer, Gris Graphite, Gris Futura, Bleu de Sevres, Noir Perla, Gris Alluminium, Rouge Aden, Blanc Perle, Bleu Lucia, Gris Futura] (cycled)
IV-I-2. cycle(T… elements)▲
Une autre signature de cette méthode prend comme paramètre une ellipse qui nous permet d’ajouter un Iterable de carburants.
2.
3.
final
Iterable<
String>
iterableCarburant =
Iterables.cycle
(
"Electric"
, "Diesel"
, "GNV"
, "Hybride"
);
out.println
(
iterableCarburant);
//[Electric, Diesel, GNV, Hybride] (cycled)
IV-J. La méthode elementsEqual▲
Nous pouvons aussi comparer deux objets Iterables afin de savoir s'ils sont identiques. Pour cela nous utilisons la méthode elementsEqual(Iterable<?> iterable1, Iterable<?> iterable2). Cette méthode renvoie true en cas de succès ou false dans le cas contraire.
2.
3.
4.
final
Iterable<
String>
iterableCarburantEssence =
ImmutableList.of
(
"Essence"
);
final
Iterable<
String>
iterableCarburantEssenceSP =
ImmutableList.of
(
"Essence"
, "Essence Sans Plomb 95"
, "Essence Sans Plomb 98"
);
final
boolean
elementsEqualCarburantsEssenceSP =
Iterables.elementsEqual
(
iterableCarburantEssence, iterableCarburantEssenceSP);
out.println
(
elementsEqualCarburantsEssenceSP); // false
IV-K. La méthode filter▲
IV-K-1. filter(Iterable<?> unfiltered, Class<T> desiredType)▲
Nous souhaitons positionner un filtre pour récupérer uniquement les consommations de carburants de type Float. La méthode filter(Iterable<?> unfiltered, Class<T> desiredType) permet d’effectuer cette opération.
2.
final
Iterable<
Float>
consomationsFilteredByDesiredType =
Iterables.filter
(
consommations, Float.class
);
out.println
(
consomationsFilteredByDesiredType); // [5.8, 8.5]
IV-K-2. filter(Iterable<T> unfiltered, Predicate<? super T> retainIfTrue)▲
Cette méthode dans une autre version prend un prédicat comme second paramètre. Ainsi nous pouvons récupérer uniquement les véhicules de la marque Renault si ces derniers sont présents dans notre Iterable de véhicules.
2.
3.
final
Iterable<
String>
consommationsFilteredByPredicate =
Iterables.filter
(
iterableVehicules, marqueRenault::test);
out.println
(
consommationsFilteredByPredicate); // [Renault Kangoo VP, Renault Nouveau Grand Scenic, Renault Alaskan]
// si le test du predicate est false alors la méthode filter renvoie []. Exemple: marquePeugeot::test
IV-L. La méthode find▲
IV-L-1. find(Iterable<? extends T> iterable, Predicate<? super T> predicate, T defaultValue)▲
Nous pouvons rechercher un véhicule dans notre Iterable de véhicules à l’aide d’un prédicat. Néanmoins, si ce dernier n’est pas présent, il serait pertinent d’en récupérer un par défaut. Par contre cette méthode renverra directement le premier élément correspondant au prédicat… et n’ira pas plus loin dans sa recherche.
2.
3.
4.
5.
6.
7.
8.
// on crée un iterable de la marque Peugeot
final
Iterable<
String>
iterablePeugeot =
Iterables.concat
(
Arrays.asList
(
peugeot));
final
String defaultValue =
"Peugeot 308 CC"
;
final
String findWithPredicateOrDefaultValue =
Iterables.find
(
iterablePeugeot, marquePeugeot::test, defaultValue);
// la marque Renault n'étant pas ajoutée à notre iterableVehicules, la valeur par défaut est renvoyée
//String findWithPredicateOrDafaultValue = Iterables.find(iterableVehicules, marqueRenault::test, defaultValue);
out.println
(
findWithPredicateOrDefaultValue);
// Peugeot Nouvelle SUV 3008
IV-L-2. find(Iterable<T> unfiltered, Predicate<? super T> retainIfTrue)▲
Idem que précédemment, mais sans valeur par défaut si le test du prédicat renvoie false.
2.
final
String findWithPredicate =
Iterables.find
(
iterablePeugeot, marquePeugeot::test);
out.println
(
findWithPredicate); // Peugeot Nouvelle SUV 3008
IV-M. La méthode frequency▲
Recherchons le nombre d’occurrences d’un code couleurs dans notre Iterable de couleurs. La méthode frequency(Iterable<?> iterable, @Nullable Object element) permet d’effectuer cette opération.
2.
3.
4.
final
int
frequencyCouleurs =
Iterables.frequency
(
couleurs, "Gris Futura"
);
out.println
(
frequencyCouleurs); // 2
//final long frequencyCouleursStream = couleurs.stream().filter(Predicate.isEqual("Gris Futura")).count();
//out.println(frequencyCouleursStream); // 2
IV-N. La méthode get▲
IV-N-1. get(Iterable<? extends T> iterable, int position, T defaultValue)▲
Nous pouvons récupérer un véhicule dans notre Iterable de véhicules en mentionnant une position spécifique dans l’Iterable. Cependant si ce dernier n’est pas présent, il serait pertinent d’en récupérer un par défaut.
2.
3.
4.
//final String getCouleurOrDefaultValue = Iterables.get(iterableVehicules, 3, defaultValue);
//out.println(getCouleurOrDefaultValue); // Citroen Nouvelle C-Elysée
final
String getCouleurOrDefaultValue =
Iterables.get
(
iterableVehicules, 14
, defaultValue);
out.println
(
getCouleurOrDefaultValue); // Peugeot 308 CC
IV-N-2. get(Iterable<T> iterable, int position)▲
Idem que précédemment, mais cette fois-ci sans valeur par défaut. L’index de la position spécifié doit exister !
2.
final
String getVehiculeToyota =
Iterables.get
(
iterableToyota, 2
); // Toyota Aygo X
out.println
(
getVehiculeToyota);
IV-O. La méthode getFirst▲
Nous voulons cette fois-ci récupérer le premier véhicule présent dans notre Iterable de véhicules de la marque Peugeot. La méthode getFirst(Iterable<? extends T> iterable, T defaultValue) sera utilisée pour cette action. À noter qu’ici aussi si le véhicule ne peut être récupéré une valeur par défaut sera restituée.
2.
3.
4.
5.
6.
7.
8.
final
String getFirstVehiculePeugeot =
Iterables.getFirst
(
iterablePeugeot, defaultValue);
out.println
(
getFirstVehiculePeugeot);
// on instancie un nouvel iterable de véhicules de la marque Volkswagen
Iterable<
String>
iterableVolkswagen =
new
ArrayList<>(
NB_MARQUES_VEHICULES);
// on n'ajoute aucun véhicule à cette liste, on la laisse vide
final
String defaultVolkswagen =
"Volkswagen Passat"
; // le véhicule Volkswagen par défaut
final
String getFirstVehiculeVolkswagen =
Iterables.getFirst
(
iterableVolkswagen, defaultVolkswagen);
out.println
(
getFirstVehiculeVolkswagen);
IV-P. La méthode getLast▲
IV-P-1. getLast(Iterable<? extends T> iterable, T defaultValue)▲
Nous voulons cette fois-ci récupérer le dernier véhicule présent dans notre Iterable de véhicules de la marque Peugeot. Par contre si l’Iterable est vide une valeur par défaut est renvoyée.
2.
final
String getLastVehiculePeugeot =
Iterables.getLast
(
iterablePeugeot, defaultValue);
out.println
(
getLastVehiculePeugeot);
IV-P-2. getLast(Iterable<T> iterable)▲
Idem que précédemment, mais cette fois-ci si l’Iterable est vide une exception java.util.NoSuchElementException est renvoyée.
2.
final
String getLastVehicule =
Iterables.getLast
(
iterableVehicules);
out.println
(
getLastVehicule); // Opel Corsa
IV-Q. La méthode getOnlyElement▲
IV-Q-1. getOnlyElement((Iterable<? extends T> iterable, T defaultValue)▲
Maintenant nous souhaitons récupérer un unique élément de notre Iterable en restituant toutefois une valeur par défaut si on ne parvient pas à récupérer cet élément.
2.
3.
4.
5.
6.
7.
8.
final
List<
String>
iterableMitsubishi =
new
ArrayList<>(
NB_MARQUES_VEHICULES);
iterableMitsubishi.add
(
"Mitsubishi Outlander PHEV"
); // iterableMitsubishi contient un élément
final
String defaultMitsubishi =
"Mitsubishi ASX"
; // le véhicule par défaut de la marque Mitsubishi
final
String getOnlyElementVehiculeMitsubishiWithoutDefaultValue =
Iterables.getOnlyElement
(
iterableMitsubishi, defaultMitsubishi);
// le véhicule ajouté sera affiché et pas celui par défaut
out.println
(
getOnlyElementVehiculeMitsubishiWithoutDefaultValue); // Mitsubishi Outlander PHEV
iterableMitsubishi.clear
(
); // on nettoie le contenu de iterableMitsubishi donc il n'y a plus aucun véhicule
final
String getOnlyElementVehiculeMitsubishiWithDefaultValue =
Iterables.getOnlyElement
(
iterableMitsubishi, defaultMitsubishi); out.println
(
getOnlyElementVehiculeMitsubishiWithDefaultValue); // Mitsubishi ASX
IV-Q-2. getOnlyElement(Iterable<T> iterable)▲
Idem que précédemment, mais sans restitution d’une valeur par défaut si l’élément n’est pas récupéré.
2.
3.
iterableMitsubishi.add
(
"Mitsubishi Outlander"
); // on ajoute un véhicule à iterableMitsubishi
final
String getOnlyElementVehiculeMitsubishi =
Iterables.getOnlyElement
(
iterableMitsubishi);
out.println
(
getOnlyElementVehiculeMitsubishi); // Mitsubishi Outlander
IV-R. La méthode indexOf(Iterable<T> iterable, Predicate<? super T> predicate)▲
Si nous souhaitons récupérer l’indice de la position du premier élément vérifiant un prédicat, la méthode indexOf(Iterable<T> iterable, Predicate<? super T> predicate) permet d’effectuer cette opération. Nous voulons savoir à quelle position se trouve le premier véhicule de la marque Opel dans notre Iterable de véhicules. À noter que cette méthode renvoie -1 si l’élément n’est pas présent dans l’Iterable.
2.
3.
4.
final
int
indexOfVehiculeWithPredicate =
Iterables.indexOf
(
iterableVehicules, marqueOpel::test);
out.println
(
indexOfVehiculeWithPredicate); // 9
final
int
indexOfVoitureWithPredicate =
Iterables.indexOf
(
iterableVehicules, marqueMitsubishi::test);
out.println
(
indexOfVoitureWithPredicate); // -1
IV-S. La méthode isEmpty▲
Nous pouvons également vérifier si notre Iterable est vide en utilisant la méthode isEmpty(Iterable<?> iterable).
2.
3.
4.
final
boolean
isEmptyVehiculeToyota =
Iterables.isEmpty
(
iterableToyota); // !vehicules.stream().findAny().isPresent();
out.println
(
isEmptyVehiculeToyota); // false
final
boolean
isEmptyVehiculeVolkswagen =
Iterables.isEmpty
(
iterableVolkswagen);
out.println
(
isEmptyVehiculeVolkswagen); // true
IV-T. La méthode limit▲
Par ailleurs il est aussi possible de limiter la taille de notre Iterable. La méthode limit(Iterable<T> iterable, int limitSize) permet d’effectuer cette opération. Nous ne voulons désormais que quatre types de carburants.
2.
final
Iterable<
String>
limitTypeCarburants =
Iterables.limit
(
iterableCarburant, 4
);
out.println
(
limitTypeCarburants); // [Electric, Diesel, GNV, Hybride]
IV-U. La méthode mergeSorted▲
Nous souhaitons désormais avoir un tri sur la longueur du nom des véhicules de deux Iterables. La méthode mergeSorted(Iterable<? extends Iterable<? extends T>> iterables, Comparator<? super T> comparator) permet d’effectuer cette opération.
2.
3.
4.
5.
6.
// on ajoute le véhicule Volkwagen par défaut dans notre iterableVolkswagen
iterableVolkswagen =
Arrays.asList
(
new
String[]{
defaultVolkswagen}
);
// nous voulons effectuer un tri en fonction de la longueur du nom du véhicule du plus long au plus court
final
Comparator<
String>
comparator =
(
String o1, String o2) ->
(
o2.length
(
) -
o1.length
(
));
final
Iterable<
String>
mergedSortedWithComparator =
Iterables.mergeSorted
(
ImmutableList.of
(
iterableMitsubishi, iterableVolkswagen), comparator);
out.println
(
mergedSortedWithComparator); // [Mitsubishi Outlander, Volkswagen Passat]
IV-V. La méthode paddedPartition▲
Nous pouvons également diviser notre Iterable en sous-listes immuables d’une longueur définie en remplissant la dernière liste de l’Iterable avec des valeurs nulles si nécessaire.
2.
final
Iterable<
List<
String>>
paddedPartitionVehicules =
Iterables.paddedPartition
(
iterableVehicules, NB_VEHICULES);
out.println
(
paddedPartitionVehicules); // [[Renault Kangoo VP, Renault Nouveau Grand Scenic, Renault Alaskan], [Citroen Nouvelle C-Elysée, Citroen Nemo Multispace, Citroen C4 Aircross], [Toyota Auris, Toyota Nouvelle Yaris, Toyota Aygo X ], [Opel Calibra, Opel Ascona, Opel Corsa]]
IV-W. La méthode partition▲
La méthode partition(Iterable<T> iterable, int size) effectue la même action que la méthode précédente par contre l’Iterable final peut être d’une longueur plus petite que la taille définie en second paramètre de la méthode.
2.
final
Iterable<
List<
String>>
partitionVehicules =
Iterables.partition
(
iterableVehicules, 5
);
out.println
(
partitionVehicules); // [[Renault Kangoo VP, Renault Nouveau Grand Scenic, Renault Alaskan, Citroen Nouvelle C-Elysée, Citroen Nemo Multispace], [Citroen C4 Aircross, Toyota Auris, Toyota Nouvelle Yaris, Toyota Aygo X , Opel Calibra], [Opel Ascona, Opel Corsa]]
IV-X. La méthode removeAll▲
Certains coloris ne sont plus disponibles dans notre palette de couleurs des véhicules ; nous souhaitons donc les supprimer. La méthode removeAll(Iterable<?> removeFrom, Collection<?> elementsToRemove) renverra la valeur booléenne true si l’opération de suppression a pu s’effectuer.
2.
3.
4.
5.
6.
7.
8.
final
List<
String>
iterablePaletteCouleurs =
new
ArrayList<>(
peinture.length);
iterablePaletteCouleurs.addAll
(
Arrays.asList
(
peinture));
final
Collection<
String>
couleursToRemove =
new
ArrayList<>(
);
couleursToRemove.add
(
"Bourrasque"
);
couleursToRemove.add
(
"Rouge Lucifer"
);
out.println
(
iterablePaletteCouleurs); // [Gris Shark, Gris Thorium, Bourrasque, Bleu Encre, Noir Obsidien]
final
boolean
removeAllCouleurs =
Iterables.removeAll
(
iterablePaletteCouleurs, couleursToRemove);
out.println
(
removeAllCouleurs); // true
IV-Y. La méthode removeIf▲
Il est également possible de supprimer des éléments en fonction d’un prédicat défini. Nous souhaitons supprimer les véhicules de la marque Renault sachant que notre Collection ne contient pas de véhicules de la marque Renault. Ensuite nous tenterons de supprimer les véhicules de la marque Opel.
Par contre en utilisant Java 8, si vous utilisez une Collection (comme une ArrayList<T>) il est préférable d’utiliser removeFrom.removeIf(predicate) où removeFrom est la Collection et removeIf la méthode avec le prédicat en paramètre.
2.
3.
4.
5.
6.
// Java 8 users: if removeFrom is a Collection, use removeFrom.removeIf(predicate) instead.
out.println
(
vehicules);
final
boolean
removeIfFoundMarqueRenault =
vehicules.removeIf
(
marqueRenault::test);
out.println
(
removeIfFoundMarqueRenault); // false
final
boolean
removeIfFoundMarqueOpel =
vehicules.removeIf
(
marqueOpel::test);
out.println
(
removeIfFoundMarqueOpel); // true
IV-Z. La méthode retainAll▲
Certains coloris sont plus attrayants et nous voulons les retenir dans notre sélection de palette de couleurs. La méthode retainAll(Iterable<?> removeFrom, Collection<?> elementsToRetain) renverra la valeur true si l’on a pu retenir les éléments sélectionnés.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
final
Collection<
String>
couleursToRetain =
new
ArrayList<>(
);
// on ajoute deux nouveaux coloris
couleursToRetain.add
(
"Bleu Californium"
);
couleursToRetain.add
(
"Gris Baryum"
);
// ... que l'on souhaite retenir pour la nouvelle collection
iterablePaletteCouleurs.add
(
"Bleu Californium"
);
iterablePaletteCouleurs.add
(
"Gris Baryum"
);
out.println
(
iterablePaletteCouleurs); // [Gris Shark, Gris Thorium, Bleu Encre, Noir Obsidien, Bleu Californium, Gris Baryum]
final
boolean
retainAllPeinture =
Iterables.retainAll
(
iterablePaletteCouleurs, couleursToRetain);
out.println
(
retainAllPeinture); // true car on a pu retenir nos coloris sélectionnés
out.println
(
iterablePaletteCouleurs); // [Bleu Californium, Gris Baryum]
IV-AA. La méthode size▲
Nous voulons récupérer le nombre d’éléments présents dans un Iterable ; en quelque sorte sa longueur. La méthode size(Iterable<?> iterable) permet d’effectuer cette action.
2.
final
int
nombreVehicules =
Iterables.size
(
iterableVehicules);
out.println
(
nombreVehicules); // 12
IV-AB. La méthode skip▲
Nous souhaitons effectuer un filtre sur notre gamme de véhicules en récupérant uniquement les véhicules qui sont au-delà du 3e véhicule. La méthode skip(Iterable<T> iterable, int numberToSkip) permet d’effectuer cette action.
2.
3.
final
Iterable<
String>
skipVehicules =
Iterables.skip
(
iterableVehicules, NB_VEHICULES);
// on ne veut pas les 3 premiers véhicules, mais uniquement les 9 autres
out.println
(
skipVehicules); // [Citroen Nouvelle C-Elysée, Citroen Nemo Multispace, Citroen C4 Aircross, Toyota Auris, Toyota Nouvelle Yaris, Toyota Aygo X , Opel Calibra, Opel Ascona, Opel Corsa]
IV-AC. La méthode toArray▲
Si nous souhaitons copier notre Iterable dans un tableau, nous pouvons utiliser la méthode toArray(Iterable<? extends T> iterable, Class<T> type).
2.
final
String[] toArrayVehicules =
Iterables.toArray
(
iterableVehicules, String.class
);
out.println
(
Arrays.toString
(
toArrayVehicules)); // [Renault Kangoo VP, Renault Nouveau Grand Scenic, Renault Alaskan, Citroen Nouvelle C-Elysée, Citroen Nemo Multispace, Citroen C4 Aircross, Toyota Auris, Toyota Nouvelle Yaris, Toyota Aygo X , Opel Calibra, Opel Ascona, Opel Corsa]
IV-AD. La méthode toString▲
À l’instar de la méthode toString du JDK d’Oracle, la méthode toString(Iterable<?> iterable) de la classe Iterables permet de mettre sous forme d’une chaîne de caractères un objet Iterable.
out.println
(
Iterables.toString
(
iterableToyota)); // [Toyota Auris, Toyota Nouvelle Yaris, Toyota Aygo X ]
IV-AE. La méthode transform▲
Nous souhaitons désormais augmenter le diamètre des jantes de nos véhicules. La méthode transform(Iterable<F> fromIterable, Function<? super F,? extends T> function) permet d’effectuer cette opération.
2.
3.
4.
// on décide d'augmenter le diamètre des jantes des véhicules
final
Function<
Integer, Float>
multiplier =
t ->
t *
1.14
f;
final
Iterable<
Float>
augmenterDiametreJantes =
Iterables.transform
(
iterableDiametreJantes, multiplier::apply);
out.println
(
augmenterDiametreJantes); // [14.82, 15.96, 17.1, 18.24, 19.38, 20.52]
IV-AF. La méthode tryFind▲
Dans notre Iterable de véhicules, nous souhaitons trouver des voitures de la marque Renault. Nous pouvons utiliser la méthode tryFind((Iterable<T> iterable, Predicate<? super T> predicate) en lui appliquant un prédicat.
À noter que cette méthode renvoie un objet de type Optional, car le résultat de la recherche est « optionnel ». On essaye de trouver un élément sans être sûr de pouvoir le trouver.
2.
3.
4.
out.println
(
iterableVehicules);
// équivaut à vehicules.stream().filter(marqueRenault::test).findFirst() donc renvoie le premier élément trouvé
final
Optional<
String>
tryFindMarqueRenault =
Iterables.tryFind
(
iterableVehicules, marqueRenault::test).toJavaUtil
(
);
out.println
(
tryFindMarqueRenault); // [Renault Kangoo VP, Renault Nouveau Grand Scenic, Renault Alaskan, Citroen Nouvelle C-Elysée, Citroen Nemo Multispace, Citroen C4 Aircross, Toyota Auris, Toyota Nouvelle Yaris, Toyota Aygo X , Opel Calibra, Opel Ascona, Opel Corsa]
IV-AG. La méthode unmodifiableIterable▲
Nous pouvons également rendre immuable notre Iterable en utilisant la méthode unmodifiableIterable(Iterable<? extends T> iterable).
2.
final
Iterable<
String>
unmodifiableIterableVehicules =
Iterables.unmodifiableIterable
(
iterableCarburantEssenceSP);
out.println
(
unmodifiableIterableVehicules); // [Essence, Essence Sans Plomb 95, Essence Sans Plomb 98]
V. Conclusion▲
Nous avons fait le tour des méthodes utilitaires présentes dans la classe Iterables. 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 comme d’habitude à 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 claudeLELOUP 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.