Lambda Expressions et Interfaces Fonctionnelles dans Java 8

Programming, Math, etc. · course

Browse all programmation documents

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:

Advertisement

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)".

Advertisement

@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.

Advertisement

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").

Advertisement

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...