Introduction Cas d’utilisation Syntaxe Références de méthodes
Expressions lambda en Java
Cours Java - F. Michel
1 / 27
Introduction Cas d’utilisation Syntaxe Références de méthodes
Plan
1 Introduction
2 Cas d’utilisation
3 Syntaxe
4 Référence de méthodes existantes
Cours Java - F. Michel
2 / 27
Introduction Cas d’utilisation Syntaxe Références de méthodes
Plan
1 Introduction
2 Cas d’utilisation
3 Syntaxe
4 Référence de méthodes existantes
Cours Java - F. Michel
3 / 27
Introduction Cas d’utilisation Syntaxe Références de méthodes
Pourquoi les lambdas
Les limites du tout objet à la Java
Impossible de définir une fonction en dehors d’une classe
Impossible de passer une fonction en paramètre d’une méthode
⇒ utilisation des classes internes anonymes (e.g. GUI)
⇒ beaucoup de lignes pour peu de choses
Introduction des lambdas en Java 8
⇒ Simplifier / clarifier le code
⇒ syntaxe proche de la programmation fonctionnelle
appelée aussi closure plus d’information
Cours Java - F. Michel
4 / 27
Introduction Cas d’utilisation Syntaxe Références de méthodes
Pourquoi les lambdas
Les limites du tout objet à la Java
Impossible de définir une fonction en dehors d’une classe
Impossible de passer une fonction en paramètre d’une méthode
⇒ utilisation des classes internes anonymes (e.g. GUI)
⇒ beaucoup de lignes pour peu de choses
Introduction des lambdas en Java 8
⇒ Simplifier / clarifier le code
⇒ syntaxe proche de la programmation fonctionnelle
appelée aussi closure plus d’information
Cours Java - F. Michel
4 / 27
Introduction Cas d’utilisation Syntaxe Références de méthodes
Plan
1 Introduction
2 Cas d’utilisation
3 Syntaxe
4 Référence de méthodes existantes
Cours Java - F. Michel
5 / 27
Introduction Cas d’utilisation Syntaxe Références de méthodes
Exemple de use case
Traitements sur collections : List<Person>
Person.java
p u b l i c c l a s s Person {
p u b l i c enum Sex {
MALE, FEMALE
}
S t r i n g name ;
LocalDate b i r t h d a y ;
Sex gender ;
S t r i n g emailAddress ;
p u b l i c i n t getAge ( ) {
// ...
}
public void printPerson ( ) {
// ...
}
}
Cours Java - F. Michel
6 / 27
Introduction Cas d’utilisation Syntaxe Références de méthodes
Approche 1 :
créer une méthode par traitement
Exemple dans RosterTest.java
s t a t i c L i s t <Person > r o s t e r ;
. . .
p u b l i c s t a t i c v o i d p r i n t P e r s o n s O l d e r T h a n ( L i s t <Person > r o s t e r , i n t age ) {
f o r ( Person p : r o s t e r ) {
i f ( p . getAge ( ) >= age ) {
p . printPerson ( ) ;
}
}
}
Défauts
fortement lié à l’API de Person
ne considère qu’un seul cas : plusVieuxQue
Cours Java - F. Michel
7 / 27
Introduction Cas d’utilisation Syntaxe Références de méthodes
Approche 2 :
créer une méthode plus générale
RosterTest.java
p u b l i c s t a t i c v o i d printPersonsWithinAgeRange (
L i s t <Person > r o s t e r , i n t low , i n t h i g h ) {
f o r ( Person p : r o s t e r ) {
i f ( low <= p . getAge ( ) && p . getAge ( ) < h i g h ) {
p . printPerson ( ) ;
}
}
}
Défauts
toujours fortement liée à l’API de Person
plus générique mais toujours liée à une recherche spécifique
Cours Java - F. Michel
8 / 27
Introduction Cas d’utilisation Syntaxe Références de méthodes
Approche 3 :
séparer traitement / requête
RosterTest.java
p u b l i c s t a t i c v o i d p r i n t P e r s o n s ( L i s t <Person > r o s t e r , CheckPerson t e s t e r ) {
f o r ( Person p : r o s t e r ) {
i f ( tester . test (p)) {
p . printPerson ( ) ;
}
}
}
CheckPerson.java
i n t e r f a c e CheckPerson {
boolean t e s t ( Person p ) ;
}
Cours Java - F. Michel
9 / 27
Introduction Cas d’utilisation Syntaxe Références de méthodes
Approche 3 :
séparer traitement / requête
CheckPersonEligibleForSelectiveService.java
c l a s s C h e c k P e r s o n E l i g i b l e F o r S e l e c t i v e S e r v i c e implements CheckPerson {
p u b l i c boolean t e s t ( Person p ) {
r e t u r n p . gender == Person . Sex .MALE &&
p . getAge ( ) >= 18 &&
p . getAge ( ) <= 2 5 ;
}
}
RosterTest.java
p r i n t P e r s o n s ( r o s t e r , new C h e c k P e r s o n E l i g i b l e F o r S e l e c t i v e S e r v i c e ( ) ) ;
Défaut
non liéé à l’API de Person mais nécessite une classe de plus
Cours Java - F. Michel
10 / 27
Introduction Cas d’utilisation Syntaxe Références de méthodes
Approche 4 :
utiliser une class interne anonyme
RosterTest.java
printPersons (
roster ,
new CheckPerson ( ) {
p u b l i c boolean t e s t ( Person p ) {
r e t u r n p . getGender ( ) == Person . Sex .MALE
&& p . getAge ( ) >= 18
&& p . getAge ( ) <= 2 5 ;
}
}
);
Défaut
pas de nouvelle classe mais un code assez lourd
Cours Java - F. Michel
11 / 27
Introduction Cas d’utilisation Syntaxe Références de méthodes
Approche 5 :
utiliser une lambda comme paramètre
RosterTest.java
printPersons (
roster ,
( Person p ) −> p . getGender ( ) == Person . Sex .MALE
&& p . getAge ( ) >= 18
&& p . getAge ( ) <= 25
);
Remarque
Nécessite que la méthode (signature) de l’approche 4 existe :
RosterTest.printPersons(List<Person>,
CheckPerson)
Cours Java - F. Michel
12 / 27
Introduction Cas d’utilisation Syntaxe Références de méthodes
Approche 6 :
réutiliser le JDK
à propos de CheckPerson.java
i n t e r f a c e CheckPerson {
boolean t e s t ( Person p ) ;
}
Remarques
Interface très simple : une seule méthode abstraite
⇒ Interface dite fonctionnelle
plusieurs interfaces fonctionnelles existent déjà : java.util.fonction
java.util.function.Predicate<T> propose un
trairement équivalent à CheckPerson : un test sur un type
Cours Java - F. Michel
13 / 27
Introduction Cas d’utilisation Syntaxe Références de méthodes
Approche 6 :
réutiliser le JDK
Predicate<T> à la place de CheckPerson ⇒
RosterTest.java
public s t a t i c void printPersonsWithPredicate (
L i s t <Person > r o s t e r , P r e d i c a t e <Person > t e s t e r ) {
f o r ( Person p : r o s t e r ) {
i f ( tester . test (p)) {
p . printPerson ( ) ;
}
}
}
utilisation ⇒
printPersonsWithPredicate (
roster ,
p −> p . getGender ( ) == Person . Sex .MALE
&& p . getAge ( ) >= 18
&& p . getAge ( ) <= 25
);
Cours Java - F. Michel
14 / 27
Introduction Cas d’utilisation Syntaxe Références de méthodes
Approche 7 :
plus de lambdas
Remplacer print par un autre traitement object -> void ?
public s t a t i c void printPersonsWithPredicate (
L i s t <Person > r o s t e r , P r e d i c a t e <Person > t e s t e r ) {
f o r ( Person p : r o s t e r ) {
i f ( tester . test (p)) {
p . printPerson ( ) ;
}
}
}
utilisation de java.util.function.Consumer<Y>
p u b l i c s t a t i c v o i d processPersons (
L i s t <Person > r o s t e r ,
P r e d i c a t e <Person > t e s t e r ,
Consumer<Person > b l o c k ) {
f o r ( Person p : r o s t e r ) {
i f ( tester . test (p)) {
b l o c k . accept ( p ) ;
}
}}
Cours Java - F. Michel
15 / 27
Introduction Cas d’utilisation Syntaxe Références de méthodes
Approche 7 :
processPersons(List<Person>,
Predicate<Person>, Consumer<Person>)
p u b l i c s t a t i c v o i d processPersons (
L i s t <Person > r o s t e r ,
P r e d i c a t e <Person > t e s t e r ,
Consumer<Person > b l o c k ) {
f o r ( Person p : r o s t e r ) {
i f ( tester . test (p)) {
b l o c k . accept ( p ) ;
}
}}
Utilisation de processPersons avec print
processPersons (
roster ,
p −> p . getGender ( ) == Person . Sex .MALE
&& p . getAge ( ) >= 18
&& p . getAge ( ) <= 25 ,
p −> p . p r i n t P e r s o n ( )
);
Cours Java - F. Michel
16 / 27
Introduction Cas d’utilisation Syntaxe Références de méthodes
Approche 7 suite
Consumer<Y> sur le résultat de
Function<T,R>
processPersonsWithFunction(List<Person>,
Predicate<Person>, Function<Person, String>,
Consumer<String>)
p u b l i c s t a t i c v o i d processPersonsWithFunction (
L i s t <Person > r o s t e r ,
P r e d i c a t e <Person > t e s t e r ,
Function <Person , S t r i n g > mapper ,
Consumer< S t r i n g > b l o c k ) {
f o r ( Person p : r o s t e r ) {
i f ( tester . test (p)) {
S t r i n g data = mapper . a p p l y ( p ) ;
b l o c k . accept ( data ) ;
}
}
}
Cours Java - F. Michel
17 / 27
Introduction Cas d’utilisation Syntaxe Références de méthodes
Approche 7 suite
Utilisation
p u b l i c s t a t i c v o i d processPersonsWithFunction (
L i s t <Person > r o s t e r ,
P r e d i c a t e <Person > t e s t e r ,
Function <Person , S t r i n g > mapper ,
Consumer< S t r i n g > b l o c k ) {
f o r ( Person p : r o s t e r ) {
i f ( tester . test (p)) {
S t r i n g data = mapper . a p p l y ( p ) ;
b l o c k . accept ( data ) ;
}
}
}
. . .
processPersonsWithFunction (
roster ,
p −> p . getGender ( ) == Person . Sex .MALE
&& p . getAge ( ) >= 18
&& p . getAge ( ) <= 25 ,
p −> p . getEmailAddress ( ) ,
e m a i l −> System . o u t . p r i n t l n ( e m a i l )
);
Cours Java - F. Michel
18 / 27
Introduction Cas d’utilisation Syntaxe Références de méthodes
Approche 8 : version générique
Même chose sur n’importe quels types :
p u b l i c s t a t i c <X , Y> v o i d processElements (
I t e r a b l e <X> source ,
P r e d i c a t e <X> t e s t e r ,
F u n c t i o n <X , Y> mapper ,
Consumer<Y> b l o c k ) {
f o r ( X p : source ) {
i f ( tester . test (p)) {
Y data = mapper . a p p l y ( p ) ;
b l o c k . accept ( data ) ;
}
}
}
. . .
processElements (
roster ,
p −> p . getGender ( ) == Person . Sex .MALE
&& p . getAge ( ) >= 18
&& p . getAge ( ) <= 25 ,
p −> p . getEmailAddress ( ) ,
e m a i l −> System . o u t . p r i n t l n ( e m a i l )
);
Cours Java - F. Michel
19 / 27
Introduction Cas d’utilisation Syntaxe Références de méthodes
Approche 9 : Utilisation d’opérations qui
acceptent des lambdas
Ces opérations existaient déjà :
roster
. stream ( )
. filter (
p −> p . getGender ( ) == Person . Sex .MALE
&& p . getAge ( ) >= 18
&& p . getAge ( ) <= 25)
. map( p −> p . getEmailAddress ( ) )
. forEach ( e m a i l −> System . o u t . p r i n t l n ( e m a i l ) ) ;
Cours Java - F. Michel
20 / 27
Introduction Cas d’utilisation Syntaxe Références de méthodes
Plan
1 Introduction
2 Cas d’utilisation
3 Syntaxe
4 Référence de méthodes existantes
Cours Java - F. Michel
21 / 27
Introduction Cas d’utilisation Syntaxe Références de méthodes
Syntaxe des lambdas
Une lambda expression est formée de la façon suivante :
une liste de paramètres séparés par une virgule et encadrés par
des parenthèses (si plus que deux ou 0) : (a,b) ou a ou ()
le symbole ->
un corps constitué d’une seule instruction ou d’un bloc encadré
d’accolades. Si l’instruction est unique, sa valeur est retournée.
On peut utiliser un return dans le cas contraire.
exemples équivalents
p −> p . getGender ( ) == Person . Sex .MALE
&& p . getAge ( ) >= 18
&& p . getAge ( ) <= 25
. . .
p −> {
r e t u r n p . getGender ( ) == Person . Sex .MALE
&& p . getAge ( ) >= 18
&& p . getAge ( ) <= 2 5 ;
}
Cours Java - F. Michel
22 / 27
Introduction Cas d’utilisation Syntaxe Références de méthodes
Plan
1 Introduction
2 Cas d’utilisation
3 Syntaxe
4 Référence de méthodes existantes
Cours Java - F. Michel
23 / 27
Introduction Cas d’utilisation Syntaxe Références de méthodes
Soit le code suivant
Person.java et Roster.java
p u b l i c Calendar g e t B i r t h d a y ( ) {
return birthday ;
}
p u b l i c s t a t i c i n t compareByAge ( Person a , Person b ) {
r e t u r n a . b i r t h d a y . compareTo ( b . b i r t h d a y ) ;
}
. . .
c l a s s PersonAgeComparator implements Comparator <Person > {
p u b l i c i n t compare ( Person a , Person b ) {
r e t u r n a . g e t B i r t h d a y ( ) . compareTo ( b . g e t B i r t h d a y ( ) ) ;
}
}
. . .
Person [ ] r o s t e r A s A r r a y = r o s t e r . t o A r r a y ( new Person [ r o s t e r . s i z e ( ) ] ) ;
. . .
A r r a y s . s o r t ( r o s t e r A s A r r a y , new PersonAgeComparator ( ) ) ;
Cours Java - F. Michel
24 / 27
Introduction Cas d’utilisation Syntaxe Références de méthodes
Référencement d’une méthode existante
Sachant que Comparator est une interface fonctionnelle
Roster.java
A r r a y s . s o r t ( r o s t e r A s A r r a y , new PersonAgeComparator ( ) ) ;
. . . / / r e p l a c e d by
Arrays . s o r t ( rosterAsArray ,
( Person a , Person b ) −> {
r e t u r n a . g e t B i r t h d a y ( ) . compareTo ( b . g e t B i r t h d a y ( ) ) ;
}
);
. . . / / r e p l a c e d by
A r r a y s . s o r t ( r o s t e r A s A r r a y , ( a , b ) −> Person . compareByAge ( a , b ) ) ;
. . . / / r e p l a c e d by
A r r a y s . s o r t ( r o s t e r A s A r r a y , Person : : compareByAge ) ;
Cours Java - F. Michel
25 / 27
Introduction Cas d’utilisation Syntaxe Références de méthodes
Différents types de référencement
Cours Java - F. Michel
26 / 27
Introduction Cas d’utilisation Syntaxe Références de méthodes
Conclusion
Sur les lambdas
Simplifient le code et apporte de la clarté (lorsqu’on les maîtrise)
⇒ avec modération et avec une indentation bien pensée
Ressources Web
Développons en Java sur les lambdas
10 Best Java Tutorials, Courses, and Books to learn Lambda
Ce cours reprend le tutoriel d’Oracle sur l’usage des lambdas
Cours Java - F. Michel
27 / 27