Expressions Lambda Java

Java 8 新特性Nouveautés de Java 8


Les expressions Lambda, également appelées fermetures, sont la nouvelle fonctionnalité la plus importante qui a motivé la sortie de Java 8.

Lambda permet de passer une fonction en paramètre à une méthode (les fonctions sont transmises aux méthodes en tant qu'arguments).

L'utilisation d'expressions Lambda peut rendre le code plus concis et compact.

Syntaxe

Le format de syntaxe d'une expression lambda est le suivant :

(paramètres) -> expressionou(paramètres) ->{ instructions; }

parametersest la liste des paramètres,expressionou{ statements; }est le corps de l'expression Lambda. S'il n'y a qu'un seul paramètre, les parenthèses peuvent être omises ; s'il n'y a aucun paramètre, des parenthèses vides sont toujours nécessaires.

Voici un exemple simple montrant l'utilisation d'une expression Lambda pour calculer la somme de deux nombres :

Exemple

// Utilisation d'une expression Lambda pour calculer la somme de deux nombres
MathOperation addition = (a, b) -> a + b;

// Appel de l'expression Lambda
int result = addition.operation(5, 3);
System.out.println("5 + 3 = " + result);

Dans l'exemple ci-dessus, MathOperation est une interface fonctionnelle qui contient une méthode abstraite operation. L'expression Lambda(a, b) -> a + bimplémente cette méthode abstraite, représentant l'opération d'addition des deux paramètres.

Les expressions Lambda peuvent être utilisées dans divers scénarios, notamment les opérations sur les collections, la gestion des événements, etc. Voici un exemple d'utilisation d'une expression Lambda pour parcourir une liste :

Exemple

List<String> names = Arrays.asList("Alice", "Bob", "Charlie");

// Utilisation d'une expression Lambda pour parcourir une liste
names.forEach(name -> System.out.println(name));

Les expressions Lambda introduisent un style de programmation plus fonctionnel en Java, rendant le code plus concis et lisible. Elles constituent une amélioration importante de la programmation fonctionnelle dans Java 8.


Fonctionnalités importantes

Concision

Les expressions Lambda offrent une syntaxe plus concise, particulièrement adaptée aux interfaces fonctionnelles. Comparées aux classes internes anonymes traditionnelles, les expressions Lambda rendent le code plus compact et réduisent le code répétitif.

Exemple

// Classe interne anonyme traditionnelle
Runnable runnable1 = new Runnable() {
    @Override
    public void run() {
        System.out.println("Hello World!");
    }
};

// Utilisation d'une expression Lambda
Runnable runnable2 = () -> System.out.println("Hello World!");

Prise en charge de la programmation fonctionnelle

Les expressions Lambda sont une manifestation de la programmation fonctionnelle. Elles permettent de passer des fonctions comme arguments à des méthodes ou de les renvoyer comme valeurs de retour. Cette prise en charge rend Java plus flexible en programmation fonctionnelle, permettant de mieux gérer des tâches telles que les opérations sur les collections et le calcul parallèle.

Exemple

// Passage d'une expression Lambda comme argument à une méthode
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
names.forEach(name -> System.out.println(name));

Capture de variable

Les expressions lambda peuvent accéder aux variables de la portée externe. Cette fonctionnalité est appelée capture de variable. Les expressions lambda peuvent capturer implicitement des variables locales qui sont final ou effectivement finales.

Exemple

// Capture de variable
int x = 10;
MyFunction myFunction = y -> System.out.println(x + y);
myFunction.doSomething(5); // Sortie 15

Références de méthodes

Les expressions lambda peuvent être encore simplifiées grâce aux références de méthodes. Les références de méthodes vous permettent de référencer directement des méthodes de classes ou d'objets existants sans écrire de code redondant.

Exemple

// Utilisation d'une référence de méthode
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
names.forEach(System.out::println);

Parallélisme

Les expressions lambda facilitent la mise en œuvre d'opérations parallèles. En utilisant l'API Stream combinée aux expressions lambda, le calcul parallèle peut être mis en œuvre plus facilement, ce qui améliore les performances du programme.

Exemple

// Utilisation des expressions lambda et de l'API Stream pour le calcul parallèle
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
int sum = numbers.parallelStream().mapToInt(Integer::intValue).sum();

L'introduction des expressions Lambda rend la programmation Java plus flexible et concise, et favorise le développement de la programmation fonctionnelle.


Exemples d'expressions Lambda

Exemples simples d'expressions Lambda :

// 1. 不需要参数,返回值为 5  
() -> 5  
  
// 2. 接收一个参数(数字类型),返回其2倍的值  
x -> 2 * x  
  
// 3. 接受2个参数(数字),并返回他们的差值  
(x, y) -> x – y  
  
// 4. 接收2个int型整数,返回他们的和  
(int x, int y) -> x + y  
  
// 5. 接受一个 string 对象,并在控制台打印,不返回任何值(看起来像是返回void)  
(String s) -> System.out.print(s)

Entrez le code suivant dans le fichier Java8Tester.java :

Fichier Java8Tester.java

public class Java8Tester { public static void main(String args[]){ Java8Tester tester = new Java8Tester(); //Déclaration de type MathOperation addition = (int a, int b) -> a + b; //Aucune déclaration de type MathOperation subtraction = (a, b) -> a - b; //Instruction de retour entre accolades MathOperation multiplication = (int a, int b) -> { return a * b; }; //Pas d'accolades et pas d'instruction return 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("Example"); greetService2.sayMessage("Google"); } 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); } }

Exécutez le script ci-dessus et la sortie est :

$ javac Java8Tester.java 
$ java Java8Tester
10 + 5 = 15
10 - 5 = 5
10 x 5 = 50
10 / 5 = 2
Hello Example
Hello Google

Il convient de noter les deux points suivants lors de l'utilisation des expressions Lambda :

  • Les expressions Lambda sont principalement utilisées pour définir des interfaces de type méthode pour une exécution en ligne (par exemple, une interface de méthode simple). Dans l'exemple ci-dessus, nous avons utilisé différents types d'expressions Lambda pour définir les méthodes de l'interface MathOperation, puis nous avons défini l'exécution de operation.

  • Les expressions Lambda éliminent les tracas liés à l'utilisation de méthodes anonymes et donnent à Java des capacités de programmation fonctionnelle simples mais puissantes.


Portée des variables

Les expressions lambda ne peuvent référencer que des variables locales externes marquées comme final. C'est-à-dire que les variables locales définies en dehors de la portée de la lambda ne peuvent pas être modifiées à l'intérieur de la lambda ; sinon, une erreur de compilation se produira.

Entrez le code suivant dans le fichier Java8Tester.java :

Fichier Java8Tester.java

public class Java8Tester { final static String salutation = "Hello! "; public static void main(String args[]){ GreetingService greetService1 = message -> System.out.println(salutation + message); greetService1.sayMessage("Example"); } interface GreetingService { void sayMessage(String message); } }

Exécutez le script ci-dessus et la sortie est :

$ javac Java8Tester.java 
$ java Java8Tester
Hello! Example

Nous pouvons également accéder directement aux variables locales externes dans l'expression lambda :

Fichier Java8Tester.java

public class Java8Tester { public static void main(String args[]) { final int num = 1; Converter<Integer, String> s = (param) -> System.out.println(String.valueOf(param + num)); s.convert(2); //La sortie est 3 } public interface Converter<T1, T2> { void convert(int i); } }

Les variables locales dans les expressions lambda n'ont pas besoin d'être déclarées comme final, mais elles ne doivent pas être modifiées par le code suivant (c'est-à-dire qu'elles ont implicitement une sémantique de final).

int num = 1;  
Converter<Integer, String> s = (param) -> System.out.println(String.valueOf(param + num));
s.convert(2);
num = 5;  
//报错信息:Local variable num defined in an enclosing scope must be final or effectively 
 final

Il n'est pas permis de déclarer un paramètre ou une variable locale avec le même nom qu'une variable locale à l'intérieur d'une expression Lambda.

String first = "";  
Comparator<String> comparator = (first, second) -> Integer.compare(first.length(), second.length());  //编译会出错 

Java 8 新特性Nouveautés de Java 8

Autres extensions