Bon OK on a deux ans de retard, enfin presque, mais de toute comme Java 8 n’est pas encore très présent sur le marché du travail ça ne pose pas vraiment de problème. Bref on va voir dans cet article les principales nouveautés apportées par cette itération.
Je teste mon niveau technique sur Java
Les principales nouveautés de Java 8 sont détaillées dans l’excellent livre Java 8 in action, à savoir :
Les lambdas représentent une nouvelle manière d’écrire du code, de manière plus concise qu’avant. Dans les faits ce n’est pas tout à fait ça, ça se voit si vous avez une exception dans votre lambda, mais on va dire que c’est ça.
Prenons le code suivant :
button.addEventListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println("Click");
}
});
Il est clair qu’il est inutilement lourd par rapport à ce qu’on veut faire, à savoir que quand on clique sur un bouton le message « Click » s’affiche sur la console. Avec les lambdas, on pourrait l’écrire de la sorte :
button.addEventListener(e -> System.out.println("Click"));
C’est franchement plus concis, pas vrai ?
Vous me direz, mais comment la JVM fait-elle pour s’y retrouver et savoir quelle méthode instancier ? La réponse tient en deux mots : interface fonctionnelle. Une interface fonctionnelle est une interface qui ne définit qu’une seule méthode.
Par exemple java.awt.event.ActionListener
est une interface fonctionnelle car elle ne définit qu’une seule méthode, par contre java.util.Iterator
n’en est pas une.
Mettons qu’on ait l’interface suivante :
public interface MathOperation {
public double compute(double a, double b);
}
Une implémentation de cette opération pourrait être l’addition. Sous forme de lambda elle serait écrite de la sorte :
(a, b) -> a + b
Par contre si on voulait que notre méthode soit un peu plus complexe, la syntaxe de la lambda s’alourdirait notamment avec l’usage du mot-clef return
qui est facultatif dans le cas où la lambda ne contient qu’une seule opération. Par exemple on pourrait avoir :
(a, b) -> {
double res = a + b;
System.out.println(res);
return res;
}
Les références de méthodes sont aussi un truc sympa de Java 8 introduit par les lambdas.
Mettons qu’on ait un tableau de String
dont la déclaration est comme suit :
String[] myArray = {"one", "two", "three", "four"};
Il est parfaitement possible de le trier avec la notation suivante :
Arrays.sort(myArray, String::compareToIgnoreCase);
Il est possible de passer des références de méthodes statiques, ou des références de méthodes d’instance. Dans le deuxième cas, la méthode d’instance doit bien évidemment être définie pour chacun des éléments pour lesquels la lambda doit être appliquée.
Les lambdas reposent en fait sur l’appel invokedynamic
introduit depuis Java 7 pour les langages comme Scala ou Groovy. Le problème est que les lambdas sont relativement complexes à déboguer, comme l’illustre parfaitement cet exemple. En particulier les piles d’appel sont souvent assez immondes à déboguer, et on perd facilement la trace entre l’appelant de la lambda et cette dernière.
C’est pourquoi il ne faut jamais perdre de vue les éléments suivants quand on utilise les lambdas :
Les streams sont un ajout au framework Collections en Java 8. Ils permettent en particulier d’utiliser les systèmes de map/reduce sur ces collections. On ne va pas détailler ici toutes les fonctionnalités de l’API stream, je vous renvoie vers la javadoc de cette API.
Comme indiqué, un map/reduce se divise en deux étapes :
L’avènement de ce type de programmation a eu lieu avec les processeurs multi-cores. Un exemple simple consiste par exemple à multiplier tous les éléments d’une liste par 5. En fonctionnement itératif simple, on bouclerait sur chaque élément de la liste, puis on multiplierait chacun des éléments par 5. En map/reduce, on peut par contre opérer de la manière suivante :
Le gain de performances vient du fait que le temps de calcul est cette fois divisé par le nombre de cores sur la machine. Implémenter une telle division en itératif serait très complexe.
Comme on l’a vu le map/reduce introduit avec les streams permet dans certains certains cas d’améliorer grandement les performances. Mais attention, cela ne fonctionne que dans le cas où il est possible de partitionner la collection pour faire les opérations demandées. Dans le cas contraire on peut au contraire perdre en performances.
Bref le meilleur moyen de savoir quelle implémentation est meilleure pour résoudre telle ou telle problématique est d’expérimenter. Tant que vous ne rencontrez pas de souci de performances avec votre code ne faites rien mais si un tel souci devait se faire sentir une solution pourrait passer par les streams et le map/reduce.
Comme on l’a vu, les lambdas permettent de grandement simplifier certaines notationCONCs. Attention toutefois à ne pas en abuser car le code peut être rendu assez pénible. De leur côté les streams permettent de remettre la plateforme Java au goût du jour en profitant de nos machines multicores récentes. Mais attention, il ne s’agit pas d’une recette miracle mais d’une solution qui peut être utile dans certains cas.
En attendant même si vous ne souhaitez pas utiliser le map/reduce ni les lambdas, passer à Java 8 peut être bénéfique pour bénéficier de diverses améliorations de la JVM en terme de performances et de sécurité, comme à chaque nouvelle version de cette plateforme.
Besoin de tester ton niveau en développement informatique ?
Cet article vous a plu ? Vous aimerez sûrement aussi :
Julien
Moi c’est Julien, ingénieur en informatique avec quelques années d’expérience. Je suis tombé dans la marmite étant petit, mon père avait acheté un Apple – avant même ma naissance (oui ça date !). Et maintenant je me passionne essentiellement pour tout ce qui est du monde Java et du système, les OS open source en particulier.
Au quotidien, je suis devops, bref je fais du dév, je discute avec les opérationnels, et je fais du conseil auprès des clients.
Ça n’étonnera personne si nous affirmons que le monde du développement logiciel est en constante…
En Allemagne, le travail en tandem à temps partiel, aussi appelé « jobsharing » est…
On se retrouve comme d'habitude pour le début du classement qcm saison automne ! Mais…
La saison printemps des tests techniques WeLoveDevs s'est terminée le 31 mai, et c'est Axel…
Se former en tant que développeur autodidacte peut sembler intimidant, mais c'est tout à fait…
Dans le cadre de leurs développements, les entreprises se tournent de plus en plus vers…
View Comments
Ce n'est pas les expressions lambda qui sont "complexe" à déboguer, mais la nouvelle API de Stream.
Ce serait la même chose si on utilisait des classes anonymes.
Et encore complexe c'est un bien grand mot. Comme toujours il suffit de remonter le stacktrace jusqu'à la ligne correspondant dans notre code...
a++