Java 8 a été publié le 18 mars 2014. C’est il y a longtemps, mais encore beaucoup de projets fonctionnent sur Java 8. C’est parce que c’était une version majeure avec beaucoup de nouvelles fonctionnalités. Regardons toutes les fonctionnalités passionnantes et majeures de Java 8 avec du code exemple.
Aperçu rapide des fonctionnalités de Java 8
Certaines des fonctionnalités importantes de Java 8 sont;
- La méthode forEach() dans l’interface Iterable
- Les méthodes par défaut et statiques dans les interfaces
- Interfaces fonctionnelles et expressions Lambda
- L’API Stream Java pour les opérations de données en vrac sur les collections
- L’API Java Time
- Améliorations de l’API Collection
- Améliorations de l’API de concurrence
- Améliorations de l’API Java IO
Jetons un coup d’œil sur ces fonctionnalités de Java 8. Je fournirai des extraits de code pour mieux comprendre les fonctionnalités de manière simple.
1. Méthode forEach() dans l’interface Iterable
Chaque fois que nous avons besoin de parcourir une Collection, nous devons créer un Iterator dont le seul but est de parcourir, puis nous avons la logique métier dans une boucle pour chacun des éléments de la Collection. Nous pourrions obtenir une ConcurrentModificationException si l’itérateur n’est pas utilisé correctement.
Java 8 a introduit la méthode forEach dans l’interface java.lang.Iterable afin que lors de l’écriture du code, nous nous concentrions sur la logique métier. La méthode forEach prend un objet java.util.function.Consumer en argument, ce qui aide à avoir notre logique métier à un emplacement séparé que nous pouvons réutiliser. Voyons l’utilisation de forEach avec un exemple simple.
Le nombre de lignes peut augmenter mais la méthode forEach aide à avoir la logique d’itération et la logique métier à des endroits distincts, ce qui résulte en une meilleure séparation des préoccupations et un code plus propre.
2. Méthodes par défaut et statiques dans les interfaces
Si vous lisez attentivement les détails de la méthode forEach, vous remarquerez qu’elle est définie dans l’interface Iterable mais nous savons que les interfaces ne peuvent pas avoir de corps de méthode. À partir de Java 8, les interfaces sont améliorées pour avoir une méthode avec une implémentation. Nous pouvons utiliser le mot-clé default
et static
pour créer des interfaces avec une implémentation de méthode. L’implémentation de la méthode forEach dans l’interface Iterable est la suivante :
Nous savons que Java ne fournit pas l’héritage multiple dans les classes car cela entraîne un problème de diamant. Alors comment cela sera-t-il géré avec les interfaces maintenant que les interfaces sont désormais similaires aux classes abstraites?
La solution est que le compilateur lancera une exception dans ce scénario et nous devrons fournir la logique d’implémentation dans la classe implémentant les interfaces.
Notez que les deux interfaces ont une méthode commune log() avec une logique d’implémentation.
Comme vous pouvez le voir, Interface1
a une implémentation de méthode statique qui est utilisée dans MyClass.log()
. Java 8 utilise largement les méthodes par défaut et statiques dans l’API Collection et les méthodes par défaut sont ajoutées pour que notre code reste rétrocompatible.
Si une classe dans la hiérarchie a une méthode avec la même signature, alors les méthodes par défaut deviennent sans importance. Object est la classe de base, donc si nous avons des méthodes equals(), hashCode() par défaut dans l’interface, elles deviendront sans importance. C’est pourquoi, pour une meilleure clarté, les interfaces ne sont pas autorisées à avoir des méthodes par défaut Object.
Pour plus de détails sur les changements d’interface dans Java 8, veuillez lire Les changements d’interface Java 8.
3. Interfaces Fonctionnelles et Expressions Lambda
Si vous remarquez le code d’interface ci-dessus, vous remarquerez l’annotation @FunctionalInterface. Les interfaces fonctionnelles sont un nouveau concept introduit dans Java 8. Une interface avec exactement une méthode abstraite devient une interface fonctionnelle. Nous n’avons pas besoin d’utiliser l’annotation @FunctionalInterface pour marquer une interface comme une interface fonctionnelle.
L’annotation @FunctionalInterface est une facilité pour éviter l’ajout accidentel de méthodes abstraites dans les interfaces fonctionnelles. Vous pouvez le considérer comme l’annotation @Override et il est recommandé de l’utiliser. java.lang.Runnable avec une seule méthode abstraite run() est un excellent exemple d’une interface fonctionnelle.
Un des principaux avantages de l’interface fonctionnelle est la possibilité d’utiliser des expressions lambda pour les instancier. Nous pouvons instancier une interface avec une classe anonyme mais le code semble volumineux.
Comme les interfaces fonctionnelles n’ont qu’une seule méthode, les expressions lambda peuvent facilement fournir l’implémentation de la méthode. Nous devons simplement fournir les arguments de méthode et la logique métier. Par exemple, nous pouvons écrire l’implémentation ci-dessus en utilisant une expression lambda comme suit:
Si vous avez une seule instruction dans la mise en œuvre de la méthode, nous n’avons pas besoin des accolades non plus. Par exemple, la classe anonyme de l’interface Interface1 ci-dessus peut être instanciée à l’aide d’une expression lambda comme suit :
Les expressions lambda sont donc un moyen de créer facilement des classes anonymes d’interfaces fonctionnelles. Il n’y a pas de bénéfices en matière de performances à utiliser des expressions lambda, donc je l’utiliserai avec précaution car je n’ai pas peur d’écrire quelques lignes de code supplémentaires.
A new package java.util.function
has been added with bunch of functional interfaces to provide target types for lambda expressions and method references. Lambda expressions are a huge topic, I will write a separate article on that in the future.
Vous pouvez lire le tutoriel complet à Tutoriel sur les Expressions Lambda Java 8.
4. API Java Stream pour les opérations de données en masse sur les collections
A new java.util.stream
has been added in Java 8 to perform filter/map/reduce like operations with the collection. Stream API will allow sequential as well as parallel execution. This is one of the best features for me because I work a lot with Collections and usually with Big Data, we need to filter out them based on some conditions.
L’interface Collection a été étendue avec stream() et parallelStream() les méthodes par défaut pour obtenir le Stream pour l’exécution séquentielle et parallèle. Voyons leur utilisation avec un exemple simple.
Si vous exécutez le code exemple ci-dessus, vous obtiendrez un résultat similaire à celui-ci :
Notez que les valeurs traitées en parallèle ne sont pas dans l’ordre, donc le traitement parallèle sera très utile lors de la manipulation de grandes collections.
Il n’est pas possible de couvrir tout ce qui concerne l’API Stream dans ce post, vous pouvez tout lire sur l’API Stream à Exemple de tutoriel sur l’API Stream Java 8.
5. API Java Time
Il a toujours été difficile de travailler avec Date, Time et Time Zones en java. Il n’y avait pas d’approche standard ou d’API en java pour la date et l’heure en Java. Une des bonnes additions dans Java 8 est le package java.time
qui va faciliter le processus de travail avec le temps en java.
En regardant simplement les packages de l’API Java Time, je peux sentir qu’ils seront très faciles à utiliser. Il a quelques sous-packages java.time.format qui fournit des classes pour imprimer et analyser les dates et les heures et java.time.zone qui fournit un soutien pour les fuseaux horaires et leurs règles.
La nouvelle API Temps préfère les énumérations aux constantes entières pour les mois et les jours de la semaine. Une des classes utiles est DateTimeFormatter pour convertir les objets DateTime en chaînes de caractères. Pour un tutoriel complet, rendez-vous à Exemple de tutoriel sur l’API Java Date Time.
6. Améliorations de l’API de collection
Nous avons déjà vu la méthode forEach() et l’API Stream pour les collections. Certaines nouvelles méthodes ajoutées dans l’API Collection sont :
Iterator
méthode par défautforEachRemaining(Consumer action)
pour effectuer l’action donnée pour chaque élément restant jusqu’à ce que tous les éléments aient été traités ou que l’action lève une exception.Collection
méthode par défautremoveIf(Predicate filter)
pour supprimer tous les éléments de cette collection qui satisfont le prédicat donné.Collection
méthodespliterator()
renvoyant une instance de Spliterator qui peut être utilisée pour parcourir les éléments de manière séquentielle ou en parallèle.- Map méthodes
replaceAll()
,compute()
,merge()
. - Amélioration des performances pour la classe HashMap avec collisions de clés
7. Améliorations de l’API de concurrence
Certaines améliorations importantes de l’API concurrente sont :
ConcurrentHashMap
méthodes compute(), forEach(), forEachEntry(), forEachKey(), forEachValue(), merge(), reduce() et search().CompletableFuture
qui peut être explicitement terminé (définissant sa valeur et son état).Executors
newWorkStealingPool()
méthode pour créer un pool de threads de vol de travail en utilisant tous les processeurs disponibles comme niveau cible de parallélisme.
8. Améliorations des E/S Java
Certaines améliorations des E/S que je connais sont :
Files.list(Path dir)
qui renvoie un Stream populaire de manière paresseuse, les éléments étant les entrées dans le répertoire.Files.lines(Path path)
qui lit toutes les lignes d’un fichier comme un Stream.Files.find()
qui renvoie un Stream qui est populaire de manière paresseuse avec Path en recherchant des fichiers dans un arbre de fichiers enraciné à un fichier de départ donné.BufferedReader.lines()
qui renvoie un Stream, les éléments étant les lignes lues à partir de ce BufferedReader.
Améliorations diverses du noyau API Java 8
Certaines améliorations d’API diverses qui pourraient être utiles sont :
- ThreadLocal méthode statique withInitial(Supplier fournisseur) pour créer des instances facilement.
- L’interface Comparator a été étendue avec de nombreuses méthodes statiques et par défaut pour l’ordre naturel, l’ordre inverse, etc.
- Les méthodes min(), max() et sum() dans les classes d’emballage Integer, Long et Double.
- Les méthodes logicalAnd(), logicalOr() et logicalXor() dans la classe Boolean.
- ZipFile.stream() méthode pour obtenir un Stream ordonné sur les entrées du fichier ZIP. Les entrées apparaissent dans le Stream dans l’ordre dans lequel elles apparaissent dans le répertoire central du fichier ZIP.
- Plusieurs méthodes utilitaires dans la classe Math.
- La commande
jjs
est ajoutée pour invoquer l’Engine Nashorn. - La commande
jdeps
est ajoutée pour analyser les fichiers de classe - Le pont JDBC-ODBC a été supprimé.
- L’espace mémoire PermGen a été supprimé
C’est tout pour les fonctionnalités de Java 8 avec des programmes d’exemple. Si j’ai manqué certaines fonctionnalités importantes de Java 8, faites-le moi savoir via les commentaires.
Source:
https://www.digitalocean.com/community/tutorials/java-8-features-with-examples