La nouvelle version du JDK vient avec son lot de nouveautés.
Une des plus importantes est l'ajout des lambda expressions.
Des évolutions significatives ont aussi été introduites autour de l'API Collections.
Ces évolutions fournissent une approche fonctionnelle de la manipulation d'ensembles de données.
La question de la refonte de l'API Collections au sein du JDK s'est posée au moment de la version 8 de java.
Une des solutions aurait été de la refondre intégralement.
Une autre option a été choisie en enrichissant les interfaces Collection, List, Iterable de nouvelles méthodes et en ajoutant de nouvelles interfaces comme l'interface Stream.
Un point important est le choix d'internaliser le mécanisme d'itération sur un ensemble de données.
Aujourd'hui, pour itérer sur une collection, nous n'avons pas d'autres choix que de le faire de manière séquentielle et selon l'ordre défini par la collection à parcourir.
En règle générale, c'est à l'aide d'une structure forEach, comme celle présentée ci-dessous, que l'on parcourt une collection :
for(Object o : objects){
/do something/
}
D'autres alternatives existent à l'aide d'api externe comme Guava, LambdaJ , commons-collections
Dans la version 8, le mécanisme d'itération a été internalisé. Ci-dessous un exemple de comment serait codé le parcours d'une liste :
objects.stream().forEach(/do something/);
Dans cet exemple, objects est une collection d'objets. Stream() est l'une des méthodes venant enrichir l'API existante.
Cette internalisation permet de déléguer la gestion de l'itération à l'API. De cette manière, il est possible de mettre en place des mécanismes permettant d'optimiser ou rationnaliser les traitements. par exemple :
– mise en place de la parallélisation,
– exécution paresseuse de traitement,
– le chainage des appels,
– etc.
Du fait de cette internalisation, il est possible de chaîner les traitements que l'on souhaite appliquer à une collection.
Soit le use case suivant:
Sur une collection de personne, je souhaite appliquer un traitement particulier sur toutes les personnes ayant pour métier pompier.
personnes.stream().filter(p -> p.metier==POMPIER)
.forEach(p -> /do something/);
L'exemple est ici très simple, mais l'on peut faire des choses plus compliquées et ceci de manière très explicite et concise. Vous trouverez dans l'article en lien d'autres exemples.
Lors de l'utilisation des lambda expressions, celles-ci sont traduites en instance d'interface à une méthode. Le JDK propose un jeu d'interface utilisé par les expressions lambda, ci-dessous un exemple de ces interfaces :
-Predicate : permet de filtrer selon une condition
-Block : permet d'appliquer un block de code.
-Function : permet de transformer un élément de la liste.
Parallélisation
Cette nouvelle version propose une fonctionnalité intéressante qui permet de se démarquer de l'approche séquentielle que l'on connait bien dans la version actuelle.
Cette fonctionnalité est la parallélisation des traitements appliqués sur une collection.
De plus, la mise en œuvre est très simple et transparente :
personnes.stream().parallel().filter(p -> p.metier==POMPIER)
.forEach(p -> /do something/);
Comme nous pouvons le voir sur l'exemple ci-dessus, il suffit d'appeler la méthode parallel() lors du chainage des traitements.
Ce mécanisme se base sur le projet fork/join. L'idée est de subdiviser l'ensemble des données en sous-ensembles et de traiter ces sous-ensembles.
Gestion des références null
L'équipe a décidé de ne pas gérer nativement les éléments null d'une collection. Cette gestion est laissée à la main du développeur.
Il est vrai qu'avec cette nouvelle syntaxe, il est possible de rapidement les traiter en appliquant une fonction filter() au début du chainage des traitements.
Une autre particularité de l'interface Stream est qu'elle définit des ensembles de données non bornées. En effet, une collection standard correspond à un ensemble d'une taille finie.
Cette notion est importante et doit être bien gardée à l'esprit.
Nous avons fait un tour d'horizon des possibilités qui seront offertes avec Java 8 dans le domaine de la manipulation de collections. Nous avons vu ici les grandes lignes des possibilités offertes par l'interface Stream (couplée aux expressions lambdas).
Des perspectives vraiment séduisantes !
#java #stream #lambda #java8 #fonctionnelle