I.
JAVA 8
LES FONDAMENTAUX DU LANGAGE
Attia Mehdi
Table des mati res
I. Lambda expressions (JSR 335) ....................................................................................................... 1
I.1 Lambda Target Type ....................................................................................................................... 3
I.2 Lambda Scopes ................................................................................................................................ 4
I.3 Ce que Lambda ne peut pas faire .................................................................................................... 5
II.
Interfaces fonctionnelles .................................................................................................................. 6
II.1 M thodes statiques et les m thodes par d faut. ....................................................................... 7
II.2 R f rence de m thodes et de constructeurs ............................................................................. 8
II.3
Les interfaces fonctionnelles les plus utilis es ...................................................................... 10
III. Streams .......................................................................................................................................... 14
III.1 Obtention dun stream ....................................................................................................... 15
III.2 Op rations sur les stream ................................................................................................... 16
IV. Date/Time API .............................................................................................................................. 31
V. Repeating annotations ................................................................................................................... 35
II. Lambda expressions (JSR 335)
Dans les versions ant rieures du Java, il n'existe que deux types de r f rences : des
r f rences vers des valeurs primitives, et des r f rences vers des instances d'objets. Dans
d'autres langages (Groovy, Scala, Haskell...), il est galement possible d' tablir des r f rences
vers des closures, c'est- -dire des blocs de code anonymes. Une r f rence de ce type peut alors,
comme toutes les autres, tre utilis e en tant que champ d'une classe ou en param tre d'une
m thode. Sous la pression des langages "alternatifs" et de la communaut Java, Oracle s'est
enfin d cid int grer les closures dans le langage.
Dans sa forme la plus simple, une expression lambda pourrait tre repr sent e comme une
liste des param tres s par s par des virgules, le symbole de et le corps.
Lambdas expression est consid r e comme la plus grosse nouveaut de Java 8, cest une
forme de m thode, plus compacte quune m thode standard, pour laquelle le nom est implicite
et les param tres peuvent tre omis, tout comme leur type ou une valeur de retour. Cest une
mani re simplifi e d' crire l'impl mentation d'une interface qui n'a qu'une seule m thode
abstraite (SAM).
Exemple 1 : Trier une liste de chaines de caract res
Au lieu de cr er des objets anonymes toute la journ e, Java 8 est livr avec une syntaxe
beaucoup plus courte et plus flexible, les expressions lambdas :
Attia Mehdi Java 8 les fondamentaux du langage
1
Comme vous pouvez le voir le code est beaucoup plus court et plus facile lire, et il
peut tre encore plus court puisque il est possible domettre les types de param tres et la valeur
de retour.
Remarque : Le type de retour dune expression lambda est celui de la m thode abstraite de
linterface fonctionnelle associ e cette expression.
Exemple 2 : Les expressions lambda dans les applications graphiques (GUI)
Pour traiter les v nements dans une interface utilisateur graphique (GUI), telles que les
actions de clavier et les actions de la souris, vous cr ez g n ralement des gestionnaires
d' v nements, ce qui implique g n ralement la mise en Suvre d'une interface particuli re.
Souvent, les interfaces de gestionnaire d' v nement sont des interfaces fonctionnelles; ont
tendance avoir une seule m thode.
Voici une classe anonyme qui d finit une action de la souris en Java FX :
L'invocation de m thode "btn.setOnAction" sp cifie ce qui se passe lorsque vous
s lectionnez le bouton repr sent par l'objet de "btn". Cette m thode n cessite un objet de type
"EventHandler<ActionEvent>". Linterface "EventHandler<ActionEvent>" contient une
seule m thode abstraite, "void handle(T event)" (Functional interface), donc il est possible
dutiliser l'expression lambda mis en vidence ci-dessous pour la remplacer.
Attia Mehdi Java 8 les fondamentaux du langage
2
I.1 Lambda Target Type
Dans dautres langages, le type de l'expression lambda serait une fonction; mais dans
Java, les expressions lambda sont repr sent es comme des objets, donc ils doivent avoir un type
d'objet, particulier connu sous le nom d'une interface fonctionnelle. Ce qu'on appelle le type
de cible "target type".
Puisque une interface fonctionnelle ne peut avoir qu'une seule m thode abstraite, les
types des param tres de l'expression Lambda doivent correspondre aux param tres de cette
m thode, et le type du corps de lambda doit correspondre au type de retour de la m thode. En
outre, toutes les exceptions mises dans le corps lambda doivent tre autoris s par la clause
"throws" de cette m thode dans l'interface fonctionnelle.
Consid rons
les
deux
interfaces
fonctionnelles
suivantes
(java.lang.Runnable
et java.util.concurrent.Callable<V>):
La m thode "Runnable.run" na pas une valeur de retour contrairement la m thode
"CallableV>.call"
Supposons quune m thode nom e "invoke" sera surcharg e comme suit :
Quelle m thode sera appel e par linstruction suivante :
Attia Mehdi Java 8 les fondamentaux du langage
3
La m thode "invoke (Callable <T>)" sera invoqu e parce que cette m thode renvoie
une valeur. Dans ce cas, le type de l'expression lambda " () -> done" est Callable <T>.
I.2 Lambda Scopes
Acc der des variables externes partir des expressions lambda est tr s similaire aux objets
anonymes. Il est possible dacc der aux variables locaux finals (finals) ainsi que les variables
d'instance (instance fields) et les variables statiques.
Acc der des variables locales
Nous pouvons lire des variables locales finales partir de la port e externe des expressions
lambda.
Mais contrairement aux objets anonymes la variable "num" peut tre d clar e non final. Ce
code est galement valable:
Cependant la variable "num" doit tre implicitement finale. Le code suivant ne compile pas:
Attia Mehdi Java 8 les fondamentaux du langage
4
Acc der aux fields et aux variables statiques
Contrairement aux variables locales nous avons l'acc s en lecture et criture aux variables
d'instance et aux variables statiques de l'int rieur des expressions lambda.
I.3 Ce que Lambda ne peut pas faire
Il y a quelques caract ristiques que lambdas ne fournissent pas. Elles ont t consid r es
pour Java 8, mais nont pas t incluses, pour plus de simplicit et en raison de contraintes de
temps.
Acc s aux variables locales non finales
Comme il est mentionn dans la section (I.2) si une nouvelle valeur est affect e une
variable, elle ne peut pas tre utilis e dans une expression lambda. Le mot-cl "final" nest pas
n cessaire, mais la variable doit tre "effectivement finale (voir plus haut). Ce code ne compile
pas:
La transparence dexception
Si une exception contr l e peut tre lanc e l'int rieur d'une expression lambda, l'interface
fonctionnelle doit galement d clarer que cette exception contr l e peut tre lanc e aussi.
L'exception nest pas propag e la m thode contenant lexpression lambda. Ce code ne
compile pas:
Publicité
Attia Mehdi Java 8 les fondamentaux du langage
5
Flux de contr le (break, return)
Il n y a pas un moyen de sortir dune boucler et retourner une valeur comme r sultat de la
m thode qui contient lexpression lambda, par exemple :
III.
Interfaces fonctionnelles
Une interface fonctionnelle est une interface disposant une unique m thode abstraite. Le but est
de d finir la signature dune m thode qui pourra tre utilis e pour passer en param tre :
Une r f rence vers une m thode statique
Une r f rence vers une m thode dinstance
Une r f rence vers un constructeur
Une expression lambda.
M me si l'annotation @FunctionalInterface nest pas obligatoire, elle a un r le important
permettant au compilateur de forcer linterface afin quelle ne contienne quune seule m thode
abstraite. Si nous essayons de d finir plus d'une seule m thode abstraite dans une interface
annot e avec @FunctionalInterface, le compilateur affichera une erreur.
Attia Mehdi Java 8 les fondamentaux du langage
6
Une interface ne peut pas fournir une impl mentation par d faut de l'une des m thodes de
la classe Object. En particulier, cela signifie qu'il nest pas possible de fournir une
impl mentation pour les m thodes "equals", "hashCode", ou "toString" partir d'une
interface.
II.1 M thodes statiques et les m thodes par d faut.
Parmi les nouveaut s apport es par Java 8, on en trouve deux qui concernent les interfaces:
les m thodes statiques et les m thodes par d faut. Les m thodes statiques d finies sur les
interfaces fonctionnent exactement de la m me fa on que celles port es par les classes, il n'y a
donc pas grand-chose en dire. En revanche, les m thodes par d faut risquent de modifier assez
profond ment notre fa on de concevoir nos API.
En Java 7 et ant rieur, une m thode d clar e dans une interface ne fournit pas
d'impl mentation. Ce n'est qu'une signature, un contrat auquel chaque classe d riv e doit se
conformer en fournissant une impl mentation propre. Mais il arrive que plusieurs classes
similaires souhaitent partager une m me impl mentation de l'interface. Dans ce cas, deux
strat gies sont possibles :
- Factoriser le code commun dans une classe abstraite, mais il n'est pas toujours possible
de modifier la hi rarchie des classes
- Extraire le code commun dans une classe utilitaire, sous forme de m thode statique (ex:
Collections.sort()).
On conviendra qu'aucune des deux n'est r ellement satisfaisante. Heureusement, Java 8 nous
offre maintenant une troisi me possibilit en proposant une solution plus propre permettant aux
m thodes d clar es dans les interfaces d'avoir une impl mentation, il sagit bien des m thodes
par d faut. Une m thode par d faut est une m thode d'instance d finie dans une interface et
commence par le mot-cl "default", elle contient galement un corps de code. Chaque classe
qui impl mente l'interface h rite ses m thodes par d faut et peut les red finir.
Prenons un coup d'Sil sur exemple ci-dessous.
Attia Mehdi Java 8 les fondamentaux du langage
7
Linterface Formule d finit la m thode abstraite "calculer" la m thode par d faut "sqrt".
Classes concr tes nont qu' impl ment la m thode abstraite calculer.
Linterface formule est impl ment e en tant qu'objet anonyme. Le code est assez verbeux:
6 lignes de code pour une simple calcule de "sqrt (a * 100)". Dans les prochaines sections
(II.3, III) nous pr sentons un moyen plus agr able dimpl mentation dinterfaces qui poss dent
une seule m thode abstraite (Single Abstract Method interface) en Java 8.
II.2 R f rence de m thodes et de constructeurs
Une r f rence de m thode ou de constructeur est utilis e pour d finir une m thode ou un
constructeur en tant quimpl mentation de la m thode abstraite dune interface fonctionnelle,
laide du nouvel op rateur :: .
Tous constructeurs et m thodes peuvent tre utilis s comme r f rence, condition quil ny
ait aucune ambig it . Lorsque plusieurs m thodes ont le m me nom, ou lorsquune classe a
plus dun constructeur, la m thode ou le constructeur appropri est s lectionn en fonction de
la m thode abstraite de linterface fonctionnelle laquelle fait r f rence lexpression.
Attia Mehdi Java 8 les fondamentaux du langage
8
Exemples :
Voyons comment le mot-cl :: fonctionne pour les constructeurs. Nous d finissons d'abord
une classe avec diff rents constructeurs:
Ensuite, nous sp cifions une interface "PersonneFactory" pour cr er de nouvelles personnes:
Attia Mehdi Java 8 les fondamentaux du langage
9
Nous cr ons une r f rence au constructeur personne via "Person::new". Le compilateur Java
choisit automatiquement le bon constructeur en faisant correspondre la signature de
"PersonFactory.create".
Le tableau suivant pr sente quatre types de r f rences de m thode.
Type de r f rence de
m thode
Syntaxe
Exemple
Equivalence en Lambda
R f rence dune m thode
className::staticMetho
statique
dName
R f rence dune m thode
dinstance
objectName::instanceM
ethodName
R f rence dune m thode
dinstance arbitraire
className::instanceMet
hodName
String::valueOf
x -> String.valueOf(x)
s::toString
() -> s.toString()
Object::toString
x -> x.toString()
R f rence du constructeur
className::new
ArrayList::new
LinkedList<Employee>::new
() -> new ArrayList<>()
() -> new
LinkedList<Employee>()
Les R f rences des m thodes est un moyen facile pour acc der aux m thodes existantes et les
utiliser d'une mani re fonctionnelle.
II.3 Les interfaces fonctionnelles les plus utilis es
Le JDK 8 apporte par d faut plusieurs interfaces fonctionnelles, Danciennes interfaces de
lAPI ont t migr es telles que "Comparable" et "Runnable".
Nous citons ci-dessous les interfaces les plus utilis es :
Attia Mehdi Java 8 les fondamentaux du langage
10
Function
Une interface "Function" prend un argument et retourne un r sultat dont la m thode
fonctionnelle est "apply(Object)".
Publicité
@FunctionalInterface
T - le type d'entr e de la fonction
public interface Function<T,R>
R - le type du r sultat de la fonction
Linterface "Function" contient des m thodes par d faut (compose, andthen) qui peuvent tre
utilis es pour cha ner plusieurs fonctions ensemble.
Supplier
Linterface "Supplier" produise un r sultat d'un type donn e. Contrairement
linterface "Function", "Supplier" naccepte pas les arguments. La m thode abstraite de cette
interface est "get()".
@FunctionalInterface
public interface Supplier<T>
T - Le type du r sultat fournit par ce Supplier
Consumer
Linterface "Consumer" repr sente une op ration qui accepte un seul argument et ne
renvoie aucun r sultat. La m thode abstraite de cette interface est "accept(Object)".
Attia Mehdi Java 8 les fondamentaux du langage
11
@FunctionalInterface
public interface Consumer<T>
Predicate
T - le type d'entr e de la fonction
Linterface "Predicate" repr sente une op ration qui accepte un seul argument et
renvoie un r sultat de type "Boolean". La m thode abstraite de cette interface est
"test(Object)".
@FunctionalInterface
public interface Predicate<T>
T - le type d'entr e de la fonction
Linterface "Predicate" contient quelques m thodes non abstraites (par d faut) telles que :
"and (Predicate<? super T> other)", "isEqual (Object targetRef)", "negate()"
(Predicate<? super T> other)".
,"or
Comparator
Linterface "Comparator" est bien connue dans les anciennes versions du Java. Cest une
fonction de comparaison, qui impose un ordre total sur certains objets de collection via sa
m thode abstraite "compare(T o1, T o2)".
@FunctionalInterface
public interface Comparator<T>
T - le type d'objets qui peuvent tre
compar s par ce comparateur.
Java 8 ajoute dautres m thodes par d faut l'interface "Comparator" telles que
"reversed()" et "thenComparing(Comparator<? super T> other)".
Attia Mehdi Java 8 les fondamentaux du langage
12
UnaryOperator
Repr sente une op ration sur un op rande unique qui produit un r sultat du m me type que
son op rande. Cest une sp cialisation de linterface "Function" dans le cas o l'op rande et
le r sultat sont du m me type. Linterface abstraite de cette interface est "apply(Object)".
@FunctionalInterface
public interface UnaryOperator<T>
extends Function<T,T>
T - le type de l'op rande et du r sultat de
l'op ration
BiFunction
Repr sente une fonction qui accepte deux arguments et produit un r sultat. Cest la
sp cialisation de deux arit s de linterface "Function". La m thode abstraite de cette interface
est "apply(T t, U u)".
@FunctionalInterface
public interface BiFunction<T,U,R>
T - le type du premier argument
de la fonction
U
-
le
type du deuxi me
argument de la fonction
R - le type du r sultat de la
fonction
Attia Mehdi Java 8 les fondamentaux du langage
13
BinaryOperator
Repr sente une op ration deux op randes de m me type, qui produise un r sultat du m me
type que les op randes. Cest une sp cialisation de linterface "BiFunction" dans le cas o les
op randes et le r sultat sont tous du m me type.
@FunctionalInterface
public interface BinaryOperator<T>
extends BiFunction<T, T, T>
T - le type des op randes et du r sultat de
l'op ration
On a cit les interfaces fonctionnelles les plus utilis es en java 8, mais il existe plusieurs
dautres tels que "BiPredicate<T, U>", "BiConsumer<T, U>&"
IV. Streams
Java 8 arrive avec une toute nouvelle API Stream qui utilise les Lambda. Cette nouvelle
API offre la possibilit de simplifier l criture, dam liorer la performance ainsi daugmenter
la lisibilit dun certain nombre de code.
Un "Stream<T>" d crit une s quence d l ments (de type T) supportant des op rations
agr g es en s quence ou en parall le.
En voici un exemple :
Attia Mehdi Java 8 les fondamentaux du langage
14
On r cup re un "Stream<Player>" partir dune collection que lon filtre en ne prenant
que les joueurs dont le nom est "lionel". On cr e ensuite un "IntStream" (stream de int) des
salaires de ces joueurs filtr s que lon additionne. En bref, on a calcul le salaire total des
joueurs dont le nom est "lionel".
Il est important de ne pas voir les "streams" comme une alternative aux collections mais
plut t comme un moyen de traitement associ :
Un "stream" nest pas un moyen de stockage, il ne fait que transmettre des donn es
provenant dune source (collection, tableau, g n rateur de donn es, canal dE/S, &) au
travers dune file dop rations.
Un "stream" est fonctionnel par nature, une op ration sur un "stream" produit un
r sultat mais ne modifie jamais sa source. Un filtrage, par exemple, cr e un nouveau
"stream" avec les l ments filtr s, il ne supprime rien de la source.
Un "stream" a un mode dex cution paresseuse. Les op rations dun "stream" sont de
deux types : interm diaires (elles renvoient un "stream" comme le filtrage par exemple)
ou terminales (comme la somme vue plus haut). Les op rations interm diaires sont
toujours impl ment es de mani re paresseuse, afin de profiter au maximum dune
ventuelle optimisation.
Un "stream" est un consommateur, ses l ments ne peuvent tre visit s quune seule
fois pendant sa dur e de vie, un nouveau "stream" doit donc tre cr pour parcourir
nouveau la source.
III.1 Obtention dun stream
Il existe plusieurs fa ons de cr er un "stream". La plus simple consiste appeler la m thode
"stream()" ou "parallelStream()" sur une collection, de plus un certain nombre de m thodes
ont t ajout es aux classes d j existantes.
Publicité
Attia Mehdi Java 8 les fondamentaux du langage
15
Un "stream" sobtient de la mani re suivante :
Depuis une Collection via la m thode "stream()" ou "parallelStream()"
Depuis un tableau via "Arrays.stream(Object[])".
Depuis
des m thodes
statiques
de
linterface
"Stream<T>
comme
"Stream.of(Object[])",
"IntStream.range(int,int)"
ou
"Stream.iterate(Object,
UnaryOperator) ".
Lors de la lecture dun fichier via "BufferedReader.lines()".
III.2 Op rations sur les stream
Lint r t principal dun "stream" r side dans la possibilit deffectuer plusieurs op rations
plus ou moins complexes en les encha nant en une seule instruction. Cet encha nement, appel
pipeline, est compos de plusieurs op rations interm diaires et dune seule op ration terminale.
Op rations interm diaires
- Du m me type :
Chaque op ration
interm diaire
retourne un nouveau "stream"
(permettant ainsi
lencha nement des op rations).
Soit "stringCollection" une liste des String d finie comme suit :
- Stream<T> filter(Predicate<T>) : retourne un Stream<T> dont les l ments
correspondent au test du pr dicat.
Attia Mehdi Java 8 les fondamentaux du langage
16
- Stream<T> sorted() : retourne un Stream<T> tri selon lordre naturel des l ments.
Gardez en t te que "sorted" cr e seulement une vue de Stream tri e sans manipuler lordre
de la collection "stringCollection".
NB : Si T nimpl mente pas linterface Comparable, une "ClassCastException" est lev e. Pour
les "streams" ordonn s, le tri est stable, dans le cas contraire, rien nest garanti.
- Stream<T> sorted(Comparator<T> comparator)
:
identique
la m thode
pr c dente mais en pr cisant le comparateur.
- Stream<T> distinct() : retourne un Stream<T> dont les l ments sont tous distincts.
NB : T doit obligatoirement impl menter la m thode "hashCode()".
- Stream<T> limit(long maxSize) : retourne un Stream<T> limit la taille donn e.
- Stream<T> peek(Consumer<T> action) : retourne un Stream<T> avec les m mes
l ments que la source mais dont laction sp cifi e est ex cut e lors de leur
consommation.
Cette m thode est tr s pratique pour d bugger pendant la visite dun pipeline de
plusieurs op rations.
Attia Mehdi Java 8 les fondamentaux du langage
17
- Stream<T> skip(long n) : retourne un Stream<T> sans les n premiers l ments.
NB : Si le "stream" contient moins de n l ments, un "stream" vide est renvoy .
- De type diff rent
Des op rations interm diaires plus complexes peuvent changer le type du Stream :
- <R> Stream<R> map(Function<T, R> mapper) : retourne un Stream<R> dont
chaque l ment est une obtenu partir dun l ment de la source (via le mapper qui est
une fonction de transformation dun objet de type T en objet de type R).
- R> Stream<R> flatMap(Function<T, Stream<R>> mapper) : retourne un
Stream<R> contenant tous les l ments r sultants de lapplication du mapper appliqu
chaque l ment de la source. En bref, on applique une transformation 1-n chaque
l ment puis on concat ne le tout.
Nous avons d j appris comment transformer les objets d'un "stream" un autre type
d'objets en utilisant l'op ration "map". "map" est un peu limit parce que chaque objet
transform exactement un autre objet. Mais que faire si nous voulons transformer un objet en
plusieurs autres? Cest l que "flatMap" vient la rescousse.
"flatMap" transforme chaque l ment du "stream" un "stream" d'autres objets. Donc, chaque
objet sera transform en z ro, un ou plusieurs autres objets sauvegard s par des "streams". Le
Attia Mehdi Java 8 les fondamentaux du langage
18
contenu de ces "streams" sera par la suite plac dans le "stream" renvoy par l'op ration de
"flatMap".
Avant de voir en action "flatMap" nous avons besoin d'une hi rarchie de type appropri :
Ensuite, nous utilisons nos connaissances sur les "stream" d'instancier un couple d'objets:
Maintenant, nous avons une liste de trois "foos" constitu es chacune de trois "bars".
"FlatMap" accepte une fonction qui doit retourner un "stream" d'objets. Donc, afin de
r soudre les objets bar de chaque "foo", nous passons la fonction appropri e:
Attia Mehdi Java 8 les fondamentaux du langage
19
Comme vous pouvez le voir, nous avons transform un "stream" de trois objets "foo" un
"stream" de neuf objets "bar". Enfin, l'exemple ci-dessus peut tre simplifi en un seul pipeline
d'op rations de "stream" :
NB : Les m mes op rations complexes existent sur et vers les "streams" de type (IntStream,
LongStream et DoubleStream) telles que mapToInt, flatMapToInt, etc.
Op rations terminales
Lop ration terminale dun pipeline est lop ration finale, celle qui d clenche lex cution
du pipeline dop rations (et donc consomme le flux dentr e), produit ( ventuellement) un
r sultat puis ferme le "stream".
- Bool ennes
Les op rations bool ennes "allMatch", "anyMatch" et "noneMatch", qui prennent toutes
les trois un "Predicate<T>" en param tre, sont vraies lorsque, respectivement, tous les
l ments, au moins un ou aucun satisfont le pr dicat donn .
Attia Mehdi Java 8 les fondamentaux du langage
20
- Num riques
Seules 2 op rations num riques existent :
long count() : retourne le nombre d l ments du "stream".
type sum() : retourne la somme des l ments du "stream" (type tant int, double ou
long), cette m thode nexiste que sur les "streams" typ s.
- Simples
Certaines op rations renvoient un "Optional<T>" cest- -dire un objet qui peut tre soit
(null), soit un l ment du "stream":
"Optional<T>" est un conteneur dobjet permettant de g rer diff remment la nullit dune
valeur. La classe "Optional" pourrait tre manipul e via plusieurs m thodes. La m thode
Attia Mehdi Java 8 les fondamentaux du langage
21
"isPresent" nous renseigne sur lexistence dune valeur dont lacc s est donn par "get".
De plus, il est possible dajouter une valeur par d faut ou de lever une exception via les
m thodes "orElse" ou "orElseThrow").
Publicité
Optional<T> findAny() : retourne un l ment (nimporte lequel) du "stream".
Optional<T> findFirst() : retourne le premier l ment du "stream".
Optional<T> max
(Comparator<T>comparator) et Optional<T> min
(Comparator<T>comparator) retournent respectivement le maximum et le
minimum des l ments du "stream" en accord avec le comparateur donn .
- Complexes
La plupart des exemples de code de cette section utilisent la liste suivante des personnes pour
la d monstration.
Collect
"Collect" est une op ration terminale extr mement utile pour transformer les l ments
dun "stream" un autre type de r sultat, par exemple une "List", "Set" ou "Map". "Collect"
accepte un "collector" qui se compose de quatre op rations diff rentes: un "supplier", un
"accumulator", un "combiner" et un "finisher". Cela semble super-compliqu au premier
abord, mais latout de Java 8 cest quil prend en charge diverses collectors int gr s via la classe
Collectors. Donc, pour les op rations les plus courantes vous navez pas mettre en Suvre un
"Collector" par vous-m me.
Commen ons par un cas d'utilisation tr s courant:
Attia Mehdi Java 8 les fondamentaux du langage
22
Comme vous pouvez le voir, cest tr s simple construire une liste partir des l ments
d'un "stream". Si vous avez besoin d'un Set au lieu de la liste - il suffit d'utiliser
"Collectors.toSet()".
L'exemple suivant regroupe toutes les personnes selon l' ge:
"Collectors" sont extr mement polyvalent. Vous pouvez galement cr er des
agr gations sur les l ments du "stream", par exemple d terminer l' ge moyen de toutes les
personnes:
Si vous tes int ress s par des statistiques plus compl tes, vous pouvez utiliser les
m thodes
"summarizing" de
la
classe
collectors
tels que
"summarizingInt",
Attia Mehdi Java 8 les fondamentaux du langage
23
"summarizingLong" et "summarizingDouble". Donc, nous pouvons tout simplement
d terminer le min, max, somme, nombre et moyennes des ges des personnes.
Lexemple suivant ajoute les noms des personnes une chaine de caract re.
La m thode "joining" accepte un s parateur et optionnellement un pr fixe et un suffixe.
Afin de transformer les l ments du "stream" en une "Map", nous devons pr ciser comment
les cl s et les valeurs devraient tre mapp es. Gardez l'esprit que les cl s mapp es doivent
tre uniques, sinon une exception de type "IllegalStateException" est lev e. Vous pouvez
ventuellement passer une fonction de fusion comme un param tre suppl mentaire pour
contourner l'exception:
Attia Mehdi Java 8 les fondamentaux du langage
24
Maintenant que nous connaissons les principales m thodes de la classe Collectors, nous
allons essayer de construire notre propre "Collector". Nous voulons transformer toutes les
personnes du "stream" en une seule cha ne constitu e de tous les noms en lettres majuscules
s par es par le caract re "|". Pour y arriver, nous cr ons un nouveau "collector" via
"Collector.of()". Nous devons passer les quatre param tres d'un "collector": un "supplier", un
"accumulator", un "combiner" and un "finisher".
Puisque les String en Java sont immuables, nous avons besoin d'une classe comme
"StringJoiner" pour les construire avec un "collector". Le supplier construit initialement un
"StringJoiner" avec le d limiteur appropri . "Laccumulator" est utilis pour ajouter chaque
nom en majuscule la "StringJoiner". Le "combiner" sait comment fusionner deux
"StringJoiner" en une seule. Dans la derni re tape le "finisher" construit la cha ne d sir e
partir de la "StringJoiner".
- Reduce
L'op ration de r duction combine tous les l ments du "stream" en un seul r sultat. Java 8
prend en charge trois types diff rents pour r duire les m thodes. Le premier r duit un "stream"
d' l ments a exactement un l ment du "stream". Voyons comment nous pouvons utiliser cette
m thode pour d terminer la personne la plus g e:
Attia Mehdi Java 8 les fondamentaux du langage
25
Dans lexemple ci-dessus, la m thode "reduce" accepte un "BinaryOperator" pour
comparer les ges des personnes afin de retourner la personne avec l' ge maximum. La
deuxi me m thode de r duire accepte la fois une valeur d'identit "identity" et un
accumulateur "BinaryOperator". Cette m thode peut tre utilis e pour construire une nouvelle
personne avec les noms et les ges d'agr g es toutes les autres personnes dans le "stream":
La troisi me m thode de r duire accepte trois param tres: une valeur d'identit
"identity", un accumulateur "BiFunction" et une fonction de combinaison de type
"BinaryOperator". Comme le type de valeurs d'identit nest pas limit au type de personne,
nous pouvons utiliser cette r duction pour d terminer la somme des ges de toutes les
personnes:
Comme vous pouvez voir le r sultat est 107, mais quest ce qui se passe exactement en
background? Etendons le code ci-dessus par un affichage de d bogage:
Attia Mehdi Java 8 les fondamentaux du langage
26
Comme vous pouvez voir la fonction de l'accumulateur "accumulator" fait tout le
travail. Elle a d'abord tre appel e avec la valeur d'identit initiale 0 et la premi re personne
Max. Dans les trois prochaines tapes la somme augmente avec l' ge de la derni re personne
jusqu' atteindre le total de 76. La combinaison "combiner" ne sera jamais appel ? L'ex cution
du m me "stream" en parall le va lever le secret:
L'ex cution de ce "stream" en parall les implique un comportement dex cution
compl tement diff rent. Maintenant,
la combinaison est en fait appel e. Lorsque
Attia Mehdi Java 8 les fondamentaux du langage
27
l'accumulateur est appel en parall le, le combinateur est n cessaire pour additionner les valeurs
accumul es s par s.
- Order
Maintenant que nous avons appris comment cr er et travailler avec diff rents types de
"stream", nous allons plonger plus profond ment dans la fa on avec laquelle les op rations du
"stream" sont trait s sous le capot.
Une caract ristique importante des op rations interm diaires est la paresse ("laziness").
Regardez cet exemple o une op ration terminale est manquante:
On ex cutant ce bout de code, rien ne sera affich la console. Cest parce que les
op rations interm diaires ne seront ex cut s que lorsque une op ration terminale est pr sente.
tendons l'exemple ci-dessus par l'op ration terminale "forEach":
Attia Mehdi Java 8 les fondamentaux du langage
28
L'ordre du r sultat peut tre surprenant. Une approche na ve consiste ex cuter les
op rations horizontalement, lune apr s l'autre sur tous les l ments du "stream". Mais au lieu
que chaque l ment se d place le long de la cha ne verticalement, le premier l ment String
"d2" passe de la m thode "filtre" la m thode "forEach", et ce nest qu ce moment-l que
le deuxi me l ment "A2" peut tre trait . Ce comportement peut r duire le nombre r el des
op rations effectu es sur chaque l ment, comme nous le voyons dans l'exemple suivant:
L'op ration "AnyMatch" renvoie vrai d s que le pr dicat sapplique l' l ment d'entr e
donn . Cela est vrai pour le second l ment pass "A2". En raison de l'ex cution verticale de la
cha ne de "stream", dans ce cas la m thode "map" sera ex cut e seulement deux fois. Donc,
plut t...