Faire plus avec moins: Les expressions lambda de Java 8

L'utilisation des expressions lambda peut rend votre code Java plus facile à lire, fort et lisible.

L'une des critiques d'un langage de programmation est le nombre d'instructions écrites pour réaliser un traitement spécifique, et parfois vous devez écrire beaucoup de code. Les expressions Lambda ont résolues ce problème pour quelques cas et renforcent Java et le rendent plus facile, comme le cas du C# depuis des années.

Les expressions lambda sont nouvelles dans Java SE 8, et ceux sont les caractéristiques les plus remarquables ajoutées à cette version. Les expressions lambda fournissent un moyen plus clair pour représenter les méthodes et les interfaces utilisant ces expressions. Les expressions lambda améliorent aussi les collections d'objets Java en rendant le parcours des listes plus facile, filtrer et extraire les données à partir des collections. Des caractéristiques de performance renforcent Java dans des environnements multi-taches disponibles sur tous les nouveau ordinateurs modernes.

Les programmeurs ont peur que les expressions lambda vont polluer la nature orienté objet de Java avec le concept de la programmation fonctionnelle. En fait, ceux sont les mêmes critiques qui ont touchés le langage C# il y a quelques années, mais il est devenu meilleur qu'avant.

Expressions lambda et LINQ en C# et VisualBasic.Net

Les expressions lambda ont été ajoutées à C# et VB.Net, essentiellement pour supporter le LINQ(Language-Integrated Query). Les expressions lambda sont des fonctions anonymes que vous pouvez utiliser pour créer des expressions de type arbre. En C#, vous pouvez créer une expression lambda en spécifiant les paramètres d'entrées dans la coté gauche de l'opérateur lambda =>, et mettre l'expressions ou le bloc d'instructions dans l'autre coté. Par exemple, l'expression x=>x*x indique un paramètre nommé x et retourne le carré de x. En VB.Net. Dans ce cas vous utilisez des fonctions anonymes pour créer des expressions lambda.

LINQ est un ensemble de caractéristiques, introduit aussi dans Visual Studio 2008 qui a permis l'ajout de la capacité de créer des requêtes. LINQ est utile pour interroger la base de données SQL, les documents XML, l'ensemble de données ADO.Net et les collections .Net, fichiers, strings...

LINQ et les expressions lambda sont devenus populaires chez la communauté C#. Donc, Il est possible aussi que ce sera le cas pour la communauté Java.

Classes internes anonymes en Java

Les classes internes anonymes en Java ont été le premier pas vers les expressions lambda. Vous pouvez les utilisés en appelant la classe interne comme le montre l'exemple suivant:

JButton button = new JButton("test");
button.addActionListener(new ActionListener(){
@Override public void actionPerformed(ActionEvent e){
System.out.println("un clic");
}
});
La classe interne ActionListener ajoutée au bouton est une classe interne qui contient une méthode actionPerformed() dedans. Cela nous fait gagner un peu de code, mais pas trop.

Les interfaces qui définissent seulement une seule méthode sont appelées des interface fonctionnelles en java 8. Les expression lambda sont souvent utilisées avec les interfaces fonctionnelles et les classes internes.

Syntaxe des expressions lambda en Java

L'opérateur lambda en Java est ->. Comme le C#, Java 8 attache les arguments comme le montre cet exemple:

(int x) -> x * x
On a déclaré une variable x de type entier et on veut retourner le carré de cette variable x.

Considérons ces trois expressions lambda:

(int x, int y) -> x + y 

() -> 36

(String s) -> { System.out.println(s); }
Maintenant considérons l'exemple ActionListener précédent avec l'expression lambda:

JButton button = new JButton("test");
testButton.addActionListener(e -> System.out.println("un clic"));
Il est clair que ce code est plus réduit et plus lisible. On remarque aussi que la classe interne ActionListener est devenue l'argument e.

Le package java.util.function

Le package java.util.function a été ajouté dans la version java 8 et contient cinq types d'interfaces fonctionnelles:
  • Prédicat: une propriété de l'objet passé comme paramètre.
  • Consommateur: une action qui doit être déclenchée avec l'objet passé comme argument.
  • Fonction: rend un seul résultat Y:  X->Y
  • Fournisseur: contient une instance de X
  • Opérateur unaire: de X->x
  • Opérateur binaire de (X, X)->x

Collections d'objets en Java 8

Les expressions lambda peuvent améliorer l'utilisation des collections en java. Avec les versions différentes, des fonctionnalités ont été ajoutées aux collections alliant très bien avec les expressions lambda, comme la boucle forEach définie sur les deux interfaces Iterator et Iterable.

Exemple:
On veut définir une List qui contient la liste des étudiants et cette classe a comme attribut l'age de l'étudiant.

List et = Etudiant.createShortList();
Maintenant on peut définir un prédicat pour pouvoir sélectionner à partir de List.

Predicate liste = et -> et.getAge() >= 20;
Finalement, on peut faire quelque chose avec notre sélection:

uneClasse.faireqlqchose(pl, liste);
C'est beaucoup plus rapide que les versions précédente de Java. Si vous voulez accomplir un traitement plus complexe, ça aide à utiliser la méthode forEach():

et.forEach( e -> e.getNom() );
Comme conclusion, les fonctionnalités ajoutées au langage Java ne vont pas affaiblir son concept orienté objet en aucun cas. Ces fonctionnalités vont rendre le langage fort, riche et élégant.

Références: