Les expressions Java Lambda sont une nouvelle caractéristique introduite par Java 8. Ils peuvent être considérés comme un sucre de syntaxe pour la programmation fonctionnelle simulée. Ils sont similaires aux fermetures en JavaScript, mais ils sont quelque peu différents. L'objectif principal est de fournir une syntaxe fonctionnelle pour simplifier notre codage.
Syntaxe de base Lambda
La structure de base de Lambda est (arguments) -> corps, et il y a plusieurs situations:
Le corps doit inclure des instructions avec {}, et {} peut être omis lorsqu'il n'y a qu'une seule instruction.
Les méthodes d'écriture courantes sont les suivantes:
(a) -> a * a
(int a, int b) -> a + b
(a, b) -> {return a - b;}
() -> System.out.println (thread.currentThread (). GetID ())
Fonctionninterface
concept
Les expressions Java Lambda sont basées sur des interfaces fonctionnelles. Qu'est-ce qu'une interface fonctionnelle? Autrement dit, c'est une interface avec une seule méthode (fonction). Le but de ce type d'interface est pour une seule opération, ce qui équivaut à une seule fonction. Les interfaces communes telles que Runnable et Comparator sont des interfaces fonctionnelles et sont annotées avec @FunctionAliNInterface.
Donner un exemple
Il est facile de comprendre en utilisant le thread comme exemple. L'interface Runnable est une interface couramment utilisée lorsque nous avons du thread Programmation, qui comprend une méthode void run (), qui est la logique d'exécution du thread. Selon la syntaxe précédente, nous utilisons généralement une classe anonyme Runnable pour créer de nouveaux threads, comme suit:
nouveau thread (new Runnable () {@Override public void run () {System.out.println (thread.currentThread (). getID ());}}). start ();Si vous écrivez trop, n'est-ce pas ennuyeux? Les règles d'écriture basées sur Lambda deviennent concises et claires, comme suit:
nouveau thread (() -> System.out.println (thread.currentThread (). getID ())). start ();
Faites attention aux paramètres du thread. L'implémentation anonyme de Runnable est mise en œuvre en une phrase, et elle est écrite comme la suivante pour mieux comprendre.
Runnable r = () -> System.out.println (thread.currentThread (). GetID ());
nouveau thread (r) .start ();
Bien sûr, le but de Lambda n'est pas seulement d'écrire de manière concise, mais de résumer l'objectif de niveau supérieur après l'avoir compris.
Voyons un autre exemple de comparateur. Selon la méthode d'écriture traditionnelle, comme suit:
Entier [] a = {1, 8, 3, 9, 2, 0, 5}; arrays.sort (a, nouveau comparateur <Integer> () {@Override public int compare (entier o1, entier o2) {return o1 - o2;}});Les expressions de lambda sont écrites comme suit:
Entier [] a = {1, 8, 3, 9, 2, 0, 5};
Arrays.sort (A, (O1, O2) -> O1 - O2);
Interfaces fonctionnelles dans JDK
Pour que la bibliothèque de classe existante puisse utiliser directement les expressions Lambda, il y avait des interfaces dans Java 8 qui avaient été marquées comme des interfaces fonctionnelles:
Un nouveau package java.util.function a été ajouté à Java 8, apportant l'interface fonctionnelle couramment utilisée:
De plus, des fonctions plus spécifiques sont ajoutées au traitement des types de base, notamment: BooleanSupplier, DoubleBinaryOperator, DoubleConsumer, DoubleFunction <R>, DoublePredicate, DoubleSuppler, DoubleTointFunction, DoubletolongFunction IntSupplier, IntToDoubleFunction, IntToLongFunction, IntUnaryOperator, LongBinaryOperator, LongConsumer,LongFunction<R>, LongPredicate, LongSupplier, LongToDoubleFunction,LongToIntFunction, LongUnaryOperator, ToDoubleBiFunction<T, U>, ToDoubleFunction<T>,ToIntBiFunction<T, U>, tointfunction <t>, tolongbifonction <t, u>, tolongfonction <t>. Combiné avec les interfaces fonctionnelles ci-dessus, vous pouvez voir le rôle de l'interface en un coup d'œil à travers le nom de classe de ces interfaces fonctionnelles de base.
Créer une interface fonctionnelle
Parfois, nous devons implémenter nous-mêmes une interface fonctionnelle et la méthode est très simple. Tout d'abord, vous devez vous assurer que cette interface ne peut avoir qu'une seule opération de fonction, puis annoter @FunctionalInterface sur le type d'interface.
Type de dérivation
La dérivation de type est la base des expressions de lambda, et le processus de dérivation de type est le processus de compilation des expressions de lambda. Le code suivant est un exemple:
Fonction <String, Integer> strToint = Str -> Integer.ParseInt (Str);
Pendant la compilation, le processus de dérivation de type que je comprends est le suivant:
Le type cible ici est la clé, et la signature de la méthode est obtenue via le type cible, puis la compare avec l'expression de lambda.
Référence de la méthode
La base de la référence de la méthode (référence de la méthode) est également une interface fonctionnelle, qui peut être directement implémentée en tant qu'interface fonctionnelle, a la même fonction que les expressions lambda et dépend également de la dérivation de type. Les références de méthode peuvent être considérées comme une simplification des expressions de lambda qui appellent une seule méthode.
La syntaxe référencée par la méthode est: Type :: Methodname ou instanceName :: Methodname, et la méthode correspondant au constructeur est nouvelle.
Par exemple, les exemples ont été utilisés ci-dessus:
Fonction <String, Integer> strToint = Str -> Integer.ParseInt (Str);
La référence de la méthode correspondante est
Fonction <String, Integer> strToint = Integer :: paSeInt;
Selon le type de méthode, les références de méthode sont principalement divisées en types suivants: référence de méthode du constructeur, référence de méthode statique, référence de méthode d'instance sur instance, référence de méthode d'instance sur le type, etc.
Référence de la méthode du constructeur
La syntaxe est: Type :: Nouveau. Par exemple, la fonction suivante consiste à convertir une chaîne en un tableau
Écriture de référence de la méthode
Fonction <String, Integer> strToint = Integer :: new;
Lambda Writing
Fonction <String, entier> strToint = Str -> Nouveau entier (str);
Écriture traditionnelle
Fonction <String, Integer> strToint = new function <String, Integer> () {@Override public Integer applique (String str) {return new Integer (str); }};
Référence du constructeur de tableau
La syntaxe est: Type [] :: Nouveau. Par exemple, la fonction suivante consiste à construire un tableau de chaîne de longueur spécifiée
Écriture de référence de la méthode
Function <Integer, String []> fixeArray = string [] :: new;
Écriture de référence de la méthode
Function <Integer, String []> fixeArray = longueur -> new String [longueur];
Écriture traditionnelle
Function <Integer, String []> fixeArray = new function <Integer, String []> () {@Override public String [] applique (longueur entière) {return new String [length]; }};Référence de la méthode statique
La syntaxe est: Type :: Nouveau. Comme la fonction suivante est également utilisée pour convertir les chaînes en tableaux
Écriture de référence de la méthode
Fonction <String, Integer> strToint = Integer :: paSeInt;
Lambda Writing
Fonction <String, Integer> strToint = Str -> Integer.ParseInt (Str);
Écriture traditionnelle
Fonction <String, Integer> strToint = new function <String, Integer> () {@Override public Integer applique (String str) {return Integer.ParseInt (Str); }};Référence de la méthode d'instance sur une instance
La syntaxe est: instanceName :: Methodname. Par exemple, la fonction de jugement suivante est utilisée pour déterminer si le nom donné existe dans la liste
List <string> names = arrays.aslist (new String [] {"zhang san", "li si", "wang wu"});
Predicat <string> checkNameExists = noms :: contient;
System.out.println (CheckNameExists.Test ("Zhang San"));
System.out.println (CheckNameExists.Test ("Zhang Si"));
Référence de la méthode d'instance sur le type
La syntaxe est: Type :: Methodname. La référence d'exécution fait référence à un objet dans le contexte, comme la fonction ci-dessous pour renvoyer la longueur de la chaîne
Fonction <String, Integer> CalcStrLength = String :: Length; System.out.println (calcStLength.Apply ("Zhang San")); list <string> names = arrays.aslist (new String [] {"Zhangsan", "Lisi", "Wangwu"}); names.stream (). Map (String :: Length).
Par exemple, la fonction suivante a spécifié un séparateur pour diviser la chaîne en un tableau
Bifunction <string, String, String []> Split = String :: Split;
String [] names = Split.Apply ("Zhangsan, Lisi, Wangwu", ",");
System.out.println (arrays.tostring (noms));
Stream Objects
concept
Qu'est-ce que le flux? Le flux ici est différent de InputStream et OutputStream dans IO. Stream est situé dans le package java.util.stream et est également nouvellement ajouté à Java 8. Stream n'est qu'un ensemble d'éléments qui prennent en charge les opérations d'agrégation parallèle série, qui peuvent être comprises comme une version améliorée d'une collection ou d'un itérateur. Qu'est-ce qu'une opération d'agrégation? Pour donner un exemple simple, les communs incluent la moyenne, le maximum, le minimum, la somme, le tri, le filtrage, etc.
Plusieurs caractéristiques du flux:
Traitement unique. Une fois le traitement terminé, le flux actuel est fermé.
Soutenir les moyens courants pour obtenir des flux dans des opérations parallèles
Sortez de la collection
Collection.Stream ();
Collection.ParallelStream ();
Usine statique
Arrays.stream (Array)
Stream.of (t…)
IntStream.Range ()
Ici, nous ne ferons qu'une brève introduction au flux, et il y aura des applications spécifiques ci-dessous. Si vous voulez parler de la relation entre les expressions Stream et Lambda, il n'y a en fait pas de relation particulièrement étroite. C’est juste que les expressions de lambda facilitent considérablement l’utilisation du flux. Sans expressions Lambda, un grand nombre de classes anonymes seront générées lors de l'utilisation du flux, ce qui est très gênant.
Donner un exemple
Les démos suivantes dépendent de l'objet employé et de l'objet de liste composé de l'objet employé.
Employé de classe publique {nom de chaîne privée; Sexe à cordes privées; Âge privé; Employé public (nom de la chaîne, Sexe String, int Age) {super (); this.name = name; this.sex = sexe; this.age = âge; } public String getName () {Nom de retour; } public String getSEX () {return sexe; } public int getage () {return âge; } @Override public String toString () {StringBuilder builder = new StringBuilder (); builder.append ("Employee {name ="). append (name) .append (", sexe ="). append (sexe) .append (", Âge ="). A SPEND (Age) .Apnd ("}"); retour builder.toString (); }} List <employee> employés = new ArrayList <> (); employés.add (nouvel employé ("Zhang San", "Homme", 25)); employés.add (nouvel employé ("Li si", "femme", 24)); Employés.Add (New Employee ("Wang Wu", "Femme", 23)); Employés.Add (New Employee ("Saturday", "Homme", 22)); Employés.Add (New Employee ("Sun Qi", "Female", 21)); Employés.Add (New Employee ("Liu Ba", "Male", 20));Imprimer tous les employés
La collection fournit la méthode foreach pour que nous puissions utiliser des objets individuels un par un.
employés.ForEach (e -> System.out.println (e));
ou
Employés.Stream (). ForEach (e -> System.out.println (e));
Trier par âge
Collection.Sort (Employés, (E1, E2) -> e1.getage () - e2.getage ());
employés.ForEach (e -> System.out.println (e));
ou
Employés.Stream (). Tri ((e1, e2) -> e1.getage () - e2.getage ()). foreach (e -> System.out.println (e));
Imprimer la plus ancienne employée
Max / min renvoie l'élément le plus grand / min dans les conditions de tri spécifiées
Employee MaxageFemaleEmployee = Employés.Stream () .Filter (E -> "Femme" .Equals (E.GetSEx ())) .max ((E1, E2) -> e1.getage () - e2.getage ()) .get (); System.out.println (MaxageFemaleEmployee);
Imprimer des employés masculins de plus de 20 ans
filtre les éléments qui répondent aux critères
Employés.stream ()
.filter (e -> e.getage ()> 20 && "mâle" .equals (e.getSEx ()))
.ForEach (e -> System.out.println (e));
Imprimez les deux employés masculins les plus anciens
La méthode limite intercepte les éléments limités
employés.stream () .filter (e -> "mâle" .equals (e.getSEx ())) .Sorted ((e1, e2) -> e2.getage () - e1.getage ()) .limit (2) .ForEach (e -> System.out.println (e));
Imprimez les noms de tous les employés masculins, utilisez, séparez
Carte pour former un nouveau flux après avoir exécuté la fonction donnée.
String MaleEmployeesNames = Employés.Stream () .Map (e -> e.getName ()) .Collect (Collectors.joining (",")); System.out.println (MaleEmployeesNames);Informations statistiques
Intsummarystatistics, Doulessummarystatistics, Longsummarystatistics contient les données sommaires dans le flux.
Intsummarystatistics stat = employes.stream () .maptOrtIn (employee :: getage) .summarystatistics (); System.out.println ("Nombre total d'employés:" + stat.getCount ()); System.out.println ("Age maximum:" + stat.getMax ()); System.out.println ("Minimum Agel:" + "+ stat.getMin ()); System.out.println ("Age moyen:" + stat.getAvert ());Résumer
Les expressions de Lambda peuvent en effet réduire beaucoup de code et améliorer la productivité. Bien sûr, il y a des inconvénients, c'est-à-dire que les expressions complexes seront mal lisibles, ou cela peut être parce qu'ils n'y sont pas très habitués. Si vous vous y habituez, je crois que vous l'aimerez. Tout a deux côtés, cela dépend de la façon dont nous équilibrons les avantages et les inconvénients, en particulier dans une équipe.
Ce qui précède est l'information triant Java8 Javalambda. Nous continuerons d'ajouter des informations pertinentes à l'avenir. Merci pour votre soutien pour ce site Web!