Java 8 : Guide de référence rapide complet
Java 8 - Vue d'ensemble
Java 8 est une version majeure (sortie le 18 mars 2014) apportant : programmation fonctionnelle, nouveau moteur JavaScript, nouvelles API date/heure, Stream API, etc.
Nouveautés majeures
Expressions lambda : Capacité de traitement fonctionnel.
Références de méthode : Référencer des fonctions par nom au lieu de les invoquer directement.
Méthodes par défaut : Implémentation par défaut dans les interfaces.
Nouveaux outils :
jdepspour analyser les dépendances.Stream API : Traitement par pipeline déclaratif.
Date Time API : API date/heure améliorée (
java.time).Optional : Bonnes pratiques pour gérer l'absence de valeur.
Nashorn : Moteur JavaScript basé sur Java.
Exemple : Tri Java 7 vs Java 8
import java.util.Collections;
import java.util.List;
import java.util.ArrayList;
import java.util.Comparator;
public class Java8Tester {
public static void main(String args[]) {
List<String> names1 = new ArrayList<>();
names1.add("Mahesh "); names1.add("Suresh "); names1.add("Ramesh ");
names1.add("Naresh "); names1.add("Kalpesh ");
List<String> names2 = new ArrayList<>();
names2.add("Mahesh "); names2.add("Suresh "); names2.add("Ramesh ");
names2.add("Naresh "); names2.add("Kalpesh ");
Java8Tester tester = new Java8Tester();
System.out.println("Tri syntaxe Java 7 : ");
tester.sortUsingJava7(names1);
System.out.println(names1);
System.out.println("Tri syntaxe Java 8 : ");
tester.sortUsingJava8(names2);
System.out.println(names2);
}
// Tri Java 7 : classe anonyme
private void sortUsingJava7(List<String> names) {
Collections.sort(names, new Comparator<String>() {
@Override public int compare(String s1, String s2) {
return s1.compareTo(s2);
}
});
}
// Tri Java 8 : expression lambda
private void sortUsingJava8(List<String> names) {
Collections.sort(names, (s1, s2) -> s1.compareTo(s2));
}
}
Résultat :
Tri syntaxe Java 7 : [ Kalpesh Mahesh Naresh Ramesh Suresh ] Tri syntaxe Java 8 : [ Kalpesh Mahesh Naresh Ramesh Suresh ]
La méthode sortUsingJava8() utilise une expression lambda comme critère de tri.
Java 8 - Configuration de l'environnement
Installation locale
Téléchargement gratuit depuis Oracle : lien officiel. Choisissez selon votre OS, exécutez l'installeur .exe, puis configurez les variables d'environnement.
Windows (PATH)
- Clic droit « Ordinateur » → « Propriétés » → « Variables d'environnement » (onglet Avancé).
- Modifiez
Pathpour y ajouterc:\Program Files\java\jdk\bin.
Linux/UNIX (bash)
export PATH=/path/to/java:$PATH
Éditeurs Java populaires
- Notepad : Simple, pour débutants.
- NetBeans : IDE open-source gratuit (netbeans.org).
- Eclipse : IDE open-source (eclipse.org).
Java 8 - Expressions Lambda
Fonctionnalité phare de Java 8, les lambdas facilitent la programmation fonctionnelle.
Syntaxe
paramètre -> corps de l'expression
Caractéristiques :
- Type optionnel : Inférence du compilateur.
- Parenthèses optionnelles : Un seul paramètre n'en nécessite pas.
- Accolades optionnelles : Une seule instruction n'en nécessite pas.
- Mot-clé return optionnel : Retour automatique pour expression unique.
Exemple complet
public class Java8Tester {
public static void main(String args[]) {
Java8Tester tester = new Java8Tester();
// Avec déclaration de type
MathOperation addition = (int a, int b) -> a + b;
// Sans type
MathOperation subtraction = (a, b) -> a - b;
// Avec return et accolades
MathOperation multiplication = (int a, int b) -> { return a * b; };
// Sans return ni accolades
MathOperation division = (int a, int b) -> a / b;
System.out.println("10 + 5 = " + tester.operate(10, 5, addition));
System.out.println("10 - 5 = " + tester.operate(10, 5, subtraction));
System.out.println("10 x 5 = " + tester.operate(10, 5, multiplication));
System.out.println("10 / 5 = " + tester.operate(10, 5, division));
// Sans parenthèses
GreetingService greetService1 = message -> System.out.println("Hello " + message);
// Avec parenthèses
GreetingService greetService2 = (message) -> System.out.println("Hello " + message);
greetService1.sayMessage("Mahesh");
greetService2.sayMessage("Suresh");
}
interface MathOperation { int operation(int a, int b); }
interface GreetingService { void sayMessage(String message); }
private int operate(int a, int b, MathOperation mathOperation) {
return mathOperation.operation(a, b);
}
}
Résultat
10 + 5 = 15 10 - 5 = 5 10 x 5 = 50 10 / 5 = 2 Hello Mahesh Hello Suresh
Points clés :
- Les lambdas définissent l'implémentation inline d'une interface fonctionnelle (une seule méthode).
- Éliminent le besoin de classes anonymes, apportant une programmation fonctionnelle simple et puissante.
Portée des variables
Une lambda peut référencer des variables final ou effectively final (assignées une seule fois). Erreur de compilation si réassignation.
Exemple de portée
public class Java8Tester {
final static String salutation = "Hello! ";
public static void main(String args[]) {
GreetingService greetService1 = message -> System.out.println(salutation + message);
greetService1.sayMessage("Mahesh");
}
interface GreetingService { void sayMessage(String message); }
}
Résultat
Hello! Mahesh
Java 8 - Références de méthode
Pointeurs vers des méthodes par leur nom, syntaxe ::. Types : méthodes statiques, d'instance, constructeurs (TreeSet::new).
Exemple
import java.util.List;
import java.util.ArrayList;
public class Java8Tester {
public static void main(String args[]) {
List names = new ArrayList();
names.add("Mahesh"); names.add("Suresh"); names.add("Ramesh");
names.add("Naresh"); names.add("Kalpesh");
names.forEach(System.out::println); // référence de méthode statique
}
}
Résultat
Mahesh Suresh Ramesh Naresh Kalpesh
Java 8 - Interfaces fonctionnelles
Interfaces à une seule méthode abstraite. Java 8 en définit beaucoup dans java.util.function.
| N° | Interface & Description |
|---|---|
| 1 | BiConsumer<T,U> Opération acceptant deux arguments, sans résultat. |
| 2 | BiFunction<T,U,R> Fonction acceptant deux arguments, produisant un résultat. |
| 3 | BinaryOperator<T> Opération sur deux opérandes de même type, résultat du même type. |
| 4 | BiPredicate<T,U> Prédicat (booléen) à deux arguments. |
| 5 | BooleanSupplier Fournisseur de résultats booléens. |
| 6 | Consumer<T> Opération acceptant un argument, sans résultat. |
| 7 | DoubleBinaryOperator Opération sur deux doubles, résultat double. |
| 8 | DoubleConsumer Opération acceptant un double, sans résultat. |
| 9 | DoubleFunction<R> Fonction acceptant un double, produisant un résultat. |
| 10 | DoublePredicate Prédicat à un argument double. |
| 11 | DoubleSupplier Fournisseur de résultats double. |
| 12 | DoubleToIntFunction Fonction double → int. |
| 13 | DoubleToLongFunction Fonction double → long. |
| 14 | DoubleUnaryOperator Opération sur un double, résultat double. |
| 15 | Function<T,R> Fonction un argument → résultat. |
| 16 | IntBinaryOperator Opération sur deux int, résultat int. |
| 17 | IntConsumer Opération acceptant un int, sans résultat. |
| 18 | IntFunction<R> Fonction int → résultat. |
| 19 | IntPredicate Prédicat à un argument int. |
| 20 | IntSupplier Fournisseur de résultats int. |
| 21 | IntToDoubleFunction Fonction int → double. |
| 22 | IntToLongFunction Fonction int → long. |
| 23 | IntUnaryOperator Opération sur un int, résultat int. |
| 24 | LongBinaryOperator Opération sur deux long, résultat long. |
| 25 | LongConsumer Opération acceptant un long, sans résultat. |
| 26 | LongFunction<R> Fonction long → résultat. |
| 27 | LongPredicate Prédicat à un argument long. |
| 28 | LongSupplier Fournisseur de résultats long. |
| 29 | LongToDoubleFunction Fonction long → double. |
| 30 | LongToIntFunction Fonction long → int. |
| 31 | LongUnaryOperator Opération sur un long, résultat long. |
| 32 | ObjDoubleConsumer<T> Opération objet + double, sans résultat. |
| 33 | ObjIntConsumer<T> Opération objet + int, sans résultat. |
| 34 | ObjLongConsumer<T> Opération objet + long, sans résultat. |
| 35 | Predicate<T> Prédicat à un argument. |
| 36 | Supplier<T> Fournisseur de résultats. |
| 37 | ToDoubleBiFunction<T,U> Fonction deux arguments → double. |
| 38 | ToDoubleFunction<T> Fonction produisant un double. |
| 39 | ToIntBiFunction<T,U> Fonction deux arguments → int. |
| 40 | ToIntFunction<T> Fonction produisant un int. |
| 41 | ToLongBiFunction<T,U> Fonction deux arguments → long. |
| 42 | ToLongFunction<T> Fonction produisant un long. |
| 43 | UnaryOperator<T> Opération sur un opérande, résultat même type. |
Exemple avec Predicate<T>
import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;
public class Java8Tester {
public static void main(String args[]) {
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
System.out.println("Tous les nombres :");
eval(list, n -> true);
System.out.println("Nombres pairs :");
eval(list, n -> n % 2 == 0);
System.out.println("Nombres > 3 :");
eval(list, n -> n > 3);
}
public static void eval(List<Integer> list, Predicate<Integer> predicate) {
for (Integer n : list) {
if (predicate.test(n)) {
System.out.println(n + " ");
}
}
}
}
Résultat
Tous les nombres : 1 2 3 4 5 6 7 8 9 Nombres pairs : 2 4 6 8 Nombres > 3 : 4 5 6 7 8 9
Java 8 - Méthodes par défaut
Implémentation par défaut dans les interfaces pour compatibilité ascendante (ex: forEach dans Collection).
Syntaxe
public interface Vehicle {
default void print() { System.out.println("I am a vehicle!"); }
}
Gestion de multiples défauts
Si une classe implémente deux interfaces avec la même méthode par défaut :
- Surcharger la méthode dans la classe.
- Appeler
Interface.super.méthode()pour choisir l'implémentation par défaut souhaitée.
Méthodes statiques dans les interfaces
Depuis Java 8, les interfaces peuvent avoir des méthodes statiques utilitaires.
Exemple complet
public class Java8Tester {
public static void main(String args[]) {
Vehicle vehicle = new Car();
vehicle.print();
}
}
interface Vehicle {
default void print() { System.out.println("I am a vehicle!"); }
static void blowHorn() { System.out.println("Blowing horn!!!"); }
}
interface FourWheeler {
default void print() { System.out.println("I am a four wheeler!"); }
}
class Car implements Vehicle, FourWheeler {
public void print() {
Vehicle.super.print();
FourWheeler.super.print();
Vehicle.blowHorn();
System.out.println("I am a car!");
}
}
Résultat
I am a vehicle! I am a four wheeler! Blowing horn!!! I am a car!
Java 8 - Streams
Nouvelle couche abstraite pour traiter les données de façon déclarative (style SQL), tirant parti du multi-cœur sans code parallèle explicite.
Qu'est-ce qu'un Stream ?
- Séquence d'éléments : Calculés à la demande, jamais stockés.
- Source : Collections, tableaux, ressources I/O.
- Opérations d'agrégation : filter, map, limit, reduce, find, match…
- Pipelining : La plupart des opérations retournent un stream (opérations intermédiaires).
collect()est terminal. - Itérations automatiques : Pas de boucle explicite.
Génération de Streams
stream(): Stream séquentiel.parallelStream(): Stream parallèle.
Opérations courantes
- forEach : Itération (
random.ints().limit(10).forEach(System.out::println)). - map : Transformation (
.map(i -> i*i).distinct().collect(Collectors.toList())). - filter : Filtrage (
.filter(s -> s.isEmpty()).count()). - limit : Limite la taille.
- sorted : Tri.
- Parallel processing :
parallelStream()pour traitement parallèle. - Collectors :
Collectors.toList(),Collectors.joining(", "). - Statistics :
IntSummaryStatisticspour max, min, sum, average.
Exemple complet comparant Java 7 et Java 8
import java.util.ArrayList;
import java.util.Arrays;
import java.util.IntSummaryStatistics;
import java.util.List;
import java.util.Random;
import java.util.stream.Collectors;
import java.util.Map;
public class Java8Tester {
public static void main(String args[]) {
System.out.println("Using Java 7: ");
List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
System.out.println("List: " + strings);
long count = getCountEmptyStringUsingJava7(strings);
System.out.println("Empty Strings: " + count);
count = getCountLength3UsingJava7(strings);
System.out.println("Strings of length 3: " + count);
List<String> filtered = deleteEmptyStringsUsingJava7(strings);
System.out.println("Filtered List: " + filtered);
String mergedString = getMergedStringUsingJava7(strings,", ");
System.out.println("Merged String: " + mergedString);
List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);
List<Integer> squaresList = getSquares(numbers);
System.out.println("Squares List: " + squaresList);
List<Integer> integers = Arrays.asList(1,2,13,4,15,6,17,8,19);
System.out.println("List: " + integers);
System.out.println("Highest number in List : " + getMax(integers));
System.out.println("Lowest number in List : " + getMin(integers));
System.out.println("Sum of all numbers : " + getSum(integers));
System.out.println("Average of all numbers : " + getAverage(integers));
System.out.println("Random Numbers: ");
Random random = new Random();
for(int i = 0; i < 10; i++) { System.out.println(random.nextInt()); }
System.out.println("Using Java 8: ");
System.out.println("List: " + strings);
count = strings.stream().filter(string -> string.isEmpty()).count();
System.out.println("Empty Strings: " + count);
count = strings.stream().filter(string -> string.length() == 3).count();
System.out.println("Strings of length 3: " + count);
filtered = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList());
System.out.println("Filtered List: " + filtered);
mergedString = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.joining(", "));
System.out.println("Merged String: " + mergedString);
squaresList = numbers.stream().map(i -> i*i).distinct().collect(Collectors.toList());
System.out.println("Squares List: " + squaresList);
System.out.println("List: " + integers);
IntSummaryStatistics stats = integers.stream().mapToInt(x -> x).summaryStatistics();
System.out.println("Highest number in List : " + stats.getMax());
System.out.println("Lowest number in List : " + stats.getMin());
System.out.println("Sum of all numbers : " + stats.getSum());
System.out.println("Average of all numbers : " + stats.getAverage());
System.out.println("Random Numbers: ");
random.ints().limit(10).sorted().forEach(System.out::println);
count = strings.parallelStream().filter(string -> string.isEmpty()).count();
System.out.println("Empty Strings (parallel): " + count);
}
// ... méthodes Java 7 omises pour brièveté ...
}
Java 8 - Classe Optional
(Voir article dédié 1002016161 pour le détail complet)
Java 8 - Nashorn JavaScript
(Voir article dédié 1002016162 pour le détail complet)
Java 8 - Nouvelle API Date/Time
(Voir article dédié 1002016163 pour le détail complet)
Java 8 - Base64
(Voir article dédié 1002016164 pour le détail complet)
Java
- Comprendre Java Vector : Utilisation, Fonctionnalités et Comparaison avec ArrayList
- Essentiels du fraisage CNC : guide de référence rapide pour opérateur professionnel
- Maîtriser la maintenance préventive et conditionnelle : guide pratique de développement MP
- Protégez votre chaîne d'approvisionnement : stratégies d'assurance complètes
- Guide expert des machines à cintrer les tubes carrés
- Presses à froid : guide complet pour le formage efficace des métaux
- Réducteur planétaire expliqué : réduction de vitesse compacte et à couple élevé
- Fraiseuse-perceuse Jet : le guide professionnel ultime
- Presses servo : fonctionnement et avantages sur les presses mécaniques