0% ont trouvé ce document utile (0 vote)
187 vues28 pages

Java 8 : Nouveautés et Lambda-expressions

Transféré par

nab
Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd
0% ont trouvé ce document utile (0 vote)
187 vues28 pages

Java 8 : Nouveautés et Lambda-expressions

Transféré par

nab
Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd

Java 8

FIP ING 39

Serge Rosmorduc
[email protected]
Conservatoire National des Arts et Métiers

2016-2021

Serge Rosmorduc Java 8 2016-2017 1 / 28


But du cours

montrer la grande nouveauté de java 8 : les lambda-expressions ;


compléter par quelques autres nouveautés qui améliorent la vie.

Serge Rosmorduc Java 8 2016-2017 2 / 28


Méthodes par défaut dans les interfaces

une interface ne contient que des en-têtes de méthodes ;


souvent, il y a cependant une certaine redondance entre celles-ci :
1 /∗ i n t e r f a c e p o u r l e s t r u c s q u i r e s s e m b l e n t
2 à d e s t a b l e a u x ∗/
3 p u b l i c i n t e r f a c e I n d e x a b l e <T> {
4 int size ();
5
6 T get ( int i ) ;
7
8 void s e t ( i n t i , T v a l ) ;
9
10 void i n v e r s e r ( ) ;
11 }
Ici, il serait possible d’écrire la méthode inverser sans faire référence à
une implémentation.

Serge Rosmorduc Java 8 2016-2017 3 / 28


Solution usuelle en java 7
On crée une classe abstraite pour ça :
1 p u b l i c a b s t r a c t c l a s s A b s t r a c t I n d e x a b l e <T>
2 implements I n d e x a b l e <T>{
3 public void i n v e r s e r ( ) {
4 i n t i= 0 ; i n t j= s i z e ( ) −1 ;
5 while ( i < j ) {
6 T tmp= g e t ( i ) ; s e t ( i , g e t ( j ) ) ;
7 s e t ( j , tmp ) ;
8 i ++; j −−;
9 }
0 }
1 }
les classes concrètes peuvent alors, au choix
implémenter toutes les méthodes d’Indexable ;
étendre AbstractIndexable et profiter de l’implémentation
d’inverser.

Serge Rosmorduc Java 8 2016-2017 4 / 28


Méthodes par défaut

Pour diminuer cette nécessité d’utilisation d’une classe abstraite, java 8


introduit la notion de « méthode par défaut » dans une interface.
une interface peut contenir le corps d’une méthode (précédé de
default) ;
elle ne peut toujours pas contenir de variable d’instance (sinon, ce
serait une classe) ;
quand on implémente une telle interface, on n’est pas obligé de
réécrire les méthodes par défaut.
une classe peut implémenter plusieurs interfaces avec des méthodes
par défaut
s’il y a conflit (deux méthodes par défaut de même signature sont
héritées), elle doit les redéfinir ou c’est une erreur.

Serge Rosmorduc Java 8 2016-2017 5 / 28


Méthodes par défaut
1 p u b l i c i n t e r f a c e I n d e x a b l e <T> {
2 int size ();
3
4 T get ( int i ) ;
5
6 void s e t ( i n t i , T v a l ) ;
7
8 default void i n v e r s e r ( ) {
9 i n t i= 0 ; i n t j= s i z e ( ) −1 ;
0 while ( i < j ) {
1 T tmp= g e t ( i ) ;
2 set ( i , get ( j ) ) ;
3 s e t ( j , tmp ) ;
4 i ++;
5 j −−;
6 }
7 }
8 }

Serge Rosmorduc Java 8 2016-2017 6 / 28


Les fonctions comme données
1 c l a s s F i l t r e J a v a implements F i l e n a m e F i l t e r {
2 @Override
3 p u b l i c boolean a c c e p t ( F i l e d i r , S t r i n g name ) {
4 r e t u r n name . endsWith ( " . j a v a " ) ;
5 }
6 }
7
8 public class ListerJava {
9 p u b l i c s t a t i c v o i d main ( S t r i n g [ ] a r g s ) {
0 F i l e d= new F i l e ( " s r c / main / j a v a /demo/ i n t r o f o n c t i o n s " ) ;
1 f o r ( F i l e f : d.listFiles(new FiltreJava()) ) {
2 System . o u t . p r i n t l n ( f . g e t A b s o l u t e P a t h ( ) ) ;
3 }
4 }
5 }

FiltreJava sert uniquement à « enrober » la fonction accept qui fait


return name.endsWith(".java")
long et souvent peu lisible.
Serge Rosmorduc Java 8 2016-2017 7 / 28
Autre exemple

1 c l a s s MaTache implements A c t i o n L i s t e n e r {
2 @Override
3 public void actionPerformed ( ActionEvent e ) {
4 System . o u t . p r i n t l n ( "On␣ t r a v a i l l e ␣ ! ! " ) ;
5 }
6 }
7 p u b l i c c l a s s DemoTimer {
8 p u b l i c s t a t i c v o i d main ( S t r i n g [ ] a r g s ) {
9 Timer t i m e r= new Timer ( 1 0 0 0 , new MaTache ( ) ) ;
0 timer . s t a r t ( ) ;
1 }
2 }

Serge Rosmorduc Java 8 2016-2017 8 / 28


Les fonctions comme données

1 c l a s s F i l t r e J a v a implements F i l e n a m e F i l t e r {
2 @Override
3 p u b l i c boolean a c c e p t ( F i l e d i r , S t r i n g name ) {
4 r e t u r n name . endsWith ( " . j a v a " ) ;
5 }
6 }
7
8 public class ListerJava {
9 p u b l i c s t a t i c v o i d main ( S t r i n g [ ] a r g s ) {
0 F i l e d= new F i l e ( " s r c / main / j a v a /demo/ i n t r o f o n c t i o n s " ) ;
1 f o r ( F i l e f : d.listFiles(new FiltreJava()) ) {
2 System . o u t . p r i n t l n ( f . g e t A b s o l u t e P a t h ( ) ) ;
3 }
4 }
5 }

Serge Rosmorduc Java 8 2016-2017 9 / 28


Le même en java 8 ! ! !

1 public class ListerJava2 {


2 p u b l i c s t a t i c v o i d main ( S t r i n g [ ] a r g s ) {
3 F i l e d i r= new F i l e ( " s r c / main / j a v a /demo/ i n t r o f o n c t i o n s " ) ;
4 for ( F i l e f :
5 d i r . l i s t F i l e s ( (d,n) -> n.endsWith(".java") ) ) {
6 System . o u t . p r i n t l n ( f . g e t A b s o l u t e P a t h ( ) ) ;
7 }
8 }
9 }

(d,n) -> n.endsWith(".java") définit à la volée la fonction


accept ;
c’est une lambda expression.

Serge Rosmorduc Java 8 2016-2017 10 / 28


Une page de pub : les langages fonctionnels

lisp, scheme, scala, clojure, ocaml, haskell, ruby ? python ?


depuis 1958 ;
gros regain d’intérêt à cause du parallélisme.

Serge Rosmorduc Java 8 2016-2017 11 / 28


Quel est le truc ?

sucre syntaxique : on a toujours besoin d’une classe et d’un objet de


cette classe ;
mais le compilateur les crée à la volée à votre place ;
création d’une classe interne anonyme (on en reparle plus tard,
promis)
pas forcément de déclaration : inférence de types ;
une lambda peut remplacer toute valeur dont le type est une interface
fonctionnelle.

Serge Rosmorduc Java 8 2016-2017 12 / 28


Interface fonctionnelle
l’idée : une interface qui définit une et une seule fonction.
1 public interface FilenameFilter {
2 boolean a c c e p t ( F i l e d i r , S t r i n g name ) ;
3 }

On peut écrire :
1 FilenameFilter f i l t e r=
2 ( F i l e d , S t r i n g n ) −> n . endsWith ( " . c " ) ;

inférence de type : si on a
1 FilenameFilter f i l t e r=
2 ( d , n ) −> n . endsWith ( " . c " ) ;
On sait que d est de type File et n de type String.
définition : interface qui a exactement une méthode abstraite ;
elle peut avoir une ou plusieurs méthodes par défaut.

Serge Rosmorduc Java 8 2016-2017 13 / 28


Exemple

1 @FunctionalInterface
2 public interface FonctionReelle {
3 double e v a l ( double x ) ;
4
5 d e f a u l t double d e r i v e e ( double x , double d e l t a ) {
6 r e t u r n ( e v a l ( x+d e l t a ) − e v a l ( x−d e l t a ) ) / ( 2 ∗ d e l t a ) ;
7 }
8 }

Serge Rosmorduc Java 8 2016-2017 14 / 28


Lambda et collections : le filtre

idée : ne conserver que les éléments d’une collection qui vérifient un filtre
booléen.
Exemple : ne conserver que les messages de Toto :
1 L i s t <Message> r e s= new A r r a y L i s t < >();
2 f o r ( Message m: l e s M e s s a g e s ) {
3 i f (m. g e t A u t e u r ( ) . e q u a l s ( " t o t o " ) )
4 r e s . add (m) ;
5 }
type de traitement très courant... du coup :
1 L i s t <Message> r= l e s M e s s a g e s . s t r e a m ( )
2 . f i l t e r (m −> m. g e t A u t e u r ( ) . e q u a l s ( " t o t o " ) )
3 . collect ( Collectors . toList ());

Serge Rosmorduc Java 8 2016-2017 15 / 28


Lambda et collections : les streams

vue d’une collection comme une suite d’éléments auquels on applique


des fonctions ;
créés par la méthode stream()
parfois parallélisables : méthode parallelStream() de Collection ;

Serge Rosmorduc Java 8 2016-2017 16 / 28


Petite démo parallèle
1 p u b l i c c l a s s DemoTri {
2 p r i v a t e s t a t i c void time ( Runnable r ) {
3 long s t a r t = System . nanoTime ( ) ;
4 r . run ( ) ;
5 long end = System . nanoTime ( ) ;
6 System . o u t . p r i n t l n ( " Temps␣ mis ␣ " + ( end − s t a r t ) / 1 . 0 e9 )
7 }
8
9 p u b l i c s t a t i c v o i d main ( S t r i n g [ ] a r g s ) {
0 A r r a y L i s t <Double> l = new A r r a y L i s t < >();
1 f o r ( i n t i = 0 ; i < 1 _000_000 ; i ++) {
2 l . add ( Math . random ( ) ) ;
3 }
4 t i m e ( ( ) −> l . s t r e a m ( ) . s o r t e d ( ) . t o A r r a y ( ) ) ;
5 t i m e ( ( ) −> l . p a r a l l e l S t r e a m ( ) . s o r t e d ( ) . t o A r r a y ( ) ) ;
6 t i m e ( ( ) −> l . s t r e a m ( ) . s o r t e d ( ) . t o A r r a y ( ) ) ;
7 t i m e ( ( ) −> l . p a r a l l e l S t r e a m ( ) . s o r t e d ( ) . t o A r r a y ( ) ) ;
8 }
9 }
(note Serge
: premier
Rosmorducrun pas très juste) Java 8 2016-2017 17 / 28
collect

permet de « revenir » des streams aux collections (ou à d’autres types).


Rassemble les résultats d’un traitement à l’aide d’un Collector
En pratique, on utilise les collectors définis dans la classe
Collectors :
toList()
toSet()
counting
groupingBy
Collectors.joining : concaténation
...

Serge Rosmorduc Java 8 2016-2017 18 / 28


map

applique une fonction à tous les éléments du stream, et renvoie un autre


stream :
1 L i s t <S t r i n g > t i t r e s =
2 messages . stream ()
3 . map (m −> m. g e t T i t l e ( ) )
4 . collect ( Collectors . toList ());

Serge Rosmorduc Java 8 2016-2017 19 / 28


Combinaison des opérations

1 Set<S t r i n g > t i t r e s B y T o t o=
2 messages . stream ()
3 . f i l t e r (m−> m. g e t A u t h o r s ( ) . e q u a l s ( " t o t o " ) )
4 . map (m −> m. g e t T i t l e ( ) )
5 . c o l l e c t ( C o l l e c t o r s . toSet ( ) ) ;

Serge Rosmorduc Java 8 2016-2017 20 / 28


reduce

alternative à collect ;
permet de combiner les éléments du stream en un seul à l’aide d’un
opérateur ;
soit T le type des éléments du stream, et une opération f :
T ×T →T ;
alors reduce applique cette opération à tous les éléments du stream.
Exemple
1 L i s t <I n t e g e r > l= A r r a y s . a s L i s t ( 3 , 1 0 , 7 , 1 5 , 2 0 ) ;
2 System . o u t . p r i n t l n ( l . s t r e a m ( ) . r e d u c e ( 1 , ( a , b)−> a ∗b ) ) ;

Serge Rosmorduc Java 8 2016-2017 21 / 28


Pointeurs de méthodes

Il arrive très souvent de vouloir définir une lambda qui soit :


ou une méthode statique d’une classe :
1 A r r a y L i s t <S t r i n g > l= . . . ;
2 L i s t <S t r i n g > l 1= l . s t r e a m ( )
3 . map ( s −> S t r i n g U t i l s . i n v e r s e r ( s ) )
4 . collect ( Collectors . toList ());

ou une méthode des objets contenus dans le Stream :


1 A r r a y L i s t <S t r i n g > l= . . . ;
2 L i s t <S t r i n g > l 1= l . s t r e a m ( )
3 . map ( s −> s . t o U p p e r c a s e ( ) )
4 . collect ( Collectors . toList ());

pour ces deux cas, on dispose d’une notation allégée :

Serge Rosmorduc Java 8 2016-2017 22 / 28


Pointeurs de méthodes

Il arrive très souvent de vouloir définir une lambda qui soit :


ou une méthode statique d’une classe :
1 A r r a y L i s t <S t r i n g > l= . . . ;
2 L i s t <S t r i n g > l 1= l . s t r e a m ( )
3 . map ( StringUtils::inverser )
4 . collect ( Collectors . toList ());

ou une méthode des objets contenus dans le Stream :


1 A r r a y L i s t <S t r i n g > l= . . . ;
2 L i s t <S t r i n g > l 1= l . s t r e a m ( )
3 . map ( String::toUppercase )
4 . collect ( Collectors . toList ());

Serge Rosmorduc Java 8 2016-2017 23 / 28


Tony Hoare’s « Null References : The Billion Dollar
Mistake »

À propos de null :
I call it my billion-dollar mistake. It was the invention of the null
reference in 1965. At that time, I was designing the first compre-
hensive type system for references in an object oriented language
(ALGOL W). My goal was to ensure that all use of references
should be absolutely safe, with checking performed automatically
by the compiler. But I couldn’t resist the temptation to put in a
null reference, simply because it was so easy to implement. This
has led to innumerable errors, vulnerabilities, and system crashes,
which have probably caused a billion dollars of pain and damage
in the last forty years.

Serge Rosmorduc Java 8 2016-2017 24 / 28


Optional

une méthode retourne une valeur ou reçoit un argument ;


dans certains cas, on veut dire que cette valeur peut être absente ;
solution usuelle : renvoyer (ou passer) null.

Problème
Ça n’est pas explicite. Du coup, le programmeur se méfie de tout
argument ou toute valeur retournée de type objet.

Optional permet de le rendre explicite ;


ça ne résoud que partiellement le problème (il est au niveau du
langage lui-même) ;

Serge Rosmorduc Java 8 2016-2017 25 / 28


Optional

Construction
1 O p t i o n a l <I n t e g e r > a= O p t i o n a l . o f ( 3 ) ;
2 O p t i o n a l <I n t e g e r > b= O p t i o n a l . empty ( ) ;

méthodes
isPresent() : renvoie vrai si on a une valeur ;
filter/map : comme pour un stream ;
orElse(autreValeur) : la valeur (si elle est là), sinon une valeur par
défaut ;
ifPresent(Consumer consumer) : prend comme argument une fonction
qui fera quelque chose avec notre élément.
get() : renvoie la valeur (ou lève une exception).

Serge Rosmorduc Java 8 2016-2017 26 / 28


Interfaces générales

Pour faciliter la vie, java définit un certain nombre d’interfaces très


générales dans le package java.util.function :
Function<T,R> : une fonction qui prend un argument T et retourne
R;
DoubleUnaryOperator : prend un double et retourne un double ;
Consumer<R> : prend comme argument un objet de type R et
retourne void.
...

Serge Rosmorduc Java 8 2016-2017 27 / 28


λ et Comparator

En java 8, l’interface Comparator est dotée de méthodes statiques utiles


pour créer des comparateurs à la volée :
1 L i s t <P e r s o n n e > l= . . . ;
2 Collections . sort ( l ,
3 Comparator
4 . c o m p a r i n g ( P e r s o n n e : : getNom )
5 . t h e n C o m p a r i n g I n t ( P e r s o n n e : : getAge ) ) ;

Serge Rosmorduc Java 8 2016-2017 28 / 28

Vous aimerez peut-être aussi