Explication détaillée des expressions Lambda (nouvelles fonctionnalités de java8, programmation fonctionnelle)

Une nouvelle fonctionnalité importante a été introduite dans JDK1.8: les expressions Lambda.

Lambda permet aux fonctions d'être utilisées comme paramètres d'une méthode (les fonctions sont passées dans la méthode en tant que paramètres).

L'utilisation d'expressions Lambda peut rendre le code plus concis et compact. Avant d'apprendre les expressions Lambda, voyons d'abord pourquoi elles apparaissent.

1. Pourquoi l'expression Lambda apparaît-elle?

Tout d'abord, réfléchissons à la façon de représenter une valeur en java? Très simple, définissez une variable, puis affectez
Insérez la description de l'image ici

Alors, comment exprimer la logique d'exécution d'un bloc de code? C'est aussi très simple, définir une fonction et écrire la logique d'exécution correspondante sur le corps de la méthode de la fonction
Insérez la description de l'image ici

Mais que se passe-t-il si je veux attribuer cette fonction à une variable (aBlockOfCode) et la passer en tant que paramètre d'entrée?

Par exemple:

Insérez la description de l'image ici

Avant Java 8, c'était illégal. Mais après l'avènement de Java 8, en utilisant les fonctionnalités Lambda, cela peut être fait, et le concepteur de Lambda nous a également gentiment aidé à simplifier cette définition:

Insérez la description de l'image ici

Comme vous pouvez le voir, nous avons attribué "un morceau de code" à une variable de manière très élégante. Et "ce morceau de code", ou "cette fonction affectée à une variable", est une expression Lambda .

Et quel est le type de cette variable?

En Java8, un nouveau type d'interface est défini: interface fonctionnelle, un type d'interface dont une fonction d'interface doit être implémentée, nous l'appelons "interface fonctionnelle" , et une déclaration exclusive @FunctionalInterface est également définie pour cette interface , dans l'interface Ajout la déclaration ci-dessus signifie qu'une seule fonction de l'interface doit être implémentée

Insérez la description de l'image ici

En fait, nous avons constaté que l'expression ci-dessus atteint en fait le même objectif en définissant une classe d'implémentation d'une excuse puis en l'instanciant, mais la quantité de code est beaucoup plus grande.

Insérez la description de l'image ici

C'est aussi la fonction la plus intuitive des expressions Lambda: elle rend le code extrêmement concis.

Et Lambda combine de nombreuses nouvelles fonctionnalités de Java8: FunctionalInterface Lib, forEach, stream (), référence de méthode, etc. Vous verrez que cet avantage sera amplifié à l'infini!

2. La syntaxe de base des expressions Lambda

Les deux formats grammaticaux des expressions Lambda sont les suivants:

  1. (paramètres) -> expression
  2. (paramètres) -> {instructions;}

Voici les caractéristiques importantes des expressions lambda:

1. Déclaration de type facultative : il n'est pas nécessaire de déclarer le type de paramètre, le compilateur peut identifier uniformément la valeur du paramètre.

2. Parenthèses de paramètres facultatifs : un paramètre n'a pas besoin de définir de parenthèses, mais 0 ou plusieurs paramètres doivent définir des parenthèses.

3. Accolades facultatives: si l'expression n'a qu'une seule ligne, les accolades des deux côtés de l'expression peuvent être omises.

4. Mot clé de retour facultatif : si le sujet n'a qu'une seule valeur de retour d'expression, le compilateur renvoie automatiquement la valeur. Les accolades doivent spécifier que l'expression renvoie une valeur.

Exemple simple d'expression lambda

  • 1. Cas multi-paramètres

    (1). Le format de base de l'expression lambda est (x1, x2) -> {Expression ...};

    (2). Dans la formule ci-dessus, l'expression lambda a deux paramètres. Dans ce cas, le type de paramètre peut être omis, mais les parenthèses des deux côtés ne peuvent pas être omises.

    (3) ... Si l'expression n'a qu'une seule ligne, les accolades des deux côtés de l'expression peuvent être omises

    //接受2个带参参数,并返回他们的差值 
    (int x, String y) -> String.valueOf(x) + y  
    
    // 4. 接收2无参参数,返回他们的和  
    (x, y) -> x – y  
    
    
  • 2. Le cas sans paramètres

    Les parenthèses des paramètres ne peuvent pas être omises, l'autre syntaxe est la même que celle de plusieurs paramètres

//创建并启动一个线程
new Thread(()-> System.out.println("hello, i am thread!")).start();
  • 3. Le cas d'un paramètre

    Vous pouvez omettre les parenthèses et les types de paramètres, l'autre syntaxe est la même que plusieurs paramètres

//  接收一个参数,可以省略参数的括号和类型
x -> 2 * x  
 
// 接受一个 string 对象,并在控制台打印,不返回任何值(看起来像是返回void)  
(String s) -> System.out.print(s)

3. Interfaces fonctionnelles couramment utilisées fournies dans Java 8

Comme nous l'avons dit précédemment, afin de coopérer avec l'utilisation d'expressions Lambda, un nouveau type d'interface est défini dans Java 8: Interface fonctionnelle, c'est-à-dire un type d'interface qu'une fonction d'interface doit être implémentée , qui est déclaré par @FunctionalInterface . En fait, afin de faciliter notre utilisation, Java fournit également de nombreuses interfaces fonctionnelles couramment utilisées.

Utilisez le package d'interface fonctionnelle: java.util.function

Insérez la description de l'image ici

Les plus courants sont
1. Interface consommateur Consommateur : void accept (T t): reçoit un paramètre pour la consommation, mais n'a pas besoin de renvoyer un résultat.

2. Interface d'approvisionnement Fournisseur : T get (): renvoie une donnée personnalisée

3. Interface fonctionnelle Fonction <T, R> : R appliquer (T t): Passer un paramètre et renvoyer le résultat souhaité.

4. Interface d'assertion Prédicat : test booléen (T t): passe un paramètre et renvoie une valeur booléenne

5. Autres interfaces similaires :
UnaryOperator: opérateur unaire, une sous-classe de Function, mais les paramètres d'entrée et les résultats de retour de cette interface doivent être du même type.

BiFunction <T, U, R>: Un peu plus avancé que Function, il peut recevoir deux paramètres et toujours renvoyer un résultat après application.

BiConsumer <T, U>: Il est également un peu plus avancé que Consumer, et peut recevoir deux paramètres de consommation sans renvoyer le résultat.

BiPredicate <T, U>: Il est également un peu plus avancé que Predicate, il peut recevoir deux paramètres et renvoyer une valeur booléenne après jugement.

Par exemple:
Insérez la description de l'image ici

4. Référence de la méthode

Java 8 a également ajouté un nouveau mot-clé "::" Nous pouvons utiliser le mot-clé "::" pour accéder aux méthodes de construction de classe , aux méthodes objet et aux méthodes statiques .

La démonstration est la suivante:

1. Personnalisez d'abord une classe

class Demo {
    
    
    //无参构造
    Demo() {
    
    }
    //有参构造
    Demo(String something) {
    
    
        System.out.println(something);
    }
    //多参构造
    Demo(String something,Integer num) {
    
    
        System.out.println(something+num);
    }

    //静态方法
    static String startsMethod(String s) {
    
    
        return String.valueOf(s.charAt(0));
    }

    //
    String methodOne(String s) {
    
    
        return String.valueOf(s.charAt(s.length()-1));
    }

    void methodTwo() {
    
    
        System.out.println();
    }
}

2. Définissez d'abord une interface fonctionnelle

[Le transfert de l'image du lien externe a échoué. Le site d'origine peut avoir un mécanisme de lien anti-sangsue. Il est recommandé d'enregistrer l'image et de la télécharger directement (img-tEDdjg5i-1606478057603) (Explication détaillée de l'expression Lambda, nouvelle fonctionnalité de java8.assets /1606463685803.png)]

Interface IConvert, le paramètre passé est de type F et le type de retour est T.

Ensuite, montrons l'accès à la méthode via le mot clé ::.

  1. Accéder à la méthode statique

     IConvert<String,String> ic1 =  Demo::startsMethod;
    ic1.convert("静态方法访问");
    
  2. Méthode d'objet d'accès

     IConvert<String,String> ic2 =  new Demo()::methodOne;
     ic2.convert("对象方法访问");
    
  3. Constructeur d'accès

    IConvert<String,Demo> ic3 =  Demo::new;
    ic3.convert("构造方法访问");
    

Nous pouvons y penser de cette façon, en prenant l'interface IConvert <F, T> comme un modèle bien défini, et chaque méthode de la classe Demo comme l'implémentation de ce modèle. Tant que la méthode de la démo est conforme à la définition des paramètres d'entrée et de sortie de l'interface IConvert, vous pouvez directement Attribuer la méthode au modèle.

Cité en référence:
https://www.zhihu.com/question/20125256/answer/324121308

Je suppose que tu aimes

Origine blog.csdn.net/weixin_43828467/article/details/110244897
conseillé
Classement