Das erste Mal, dass ich Lambda -Ausdrücken ausgesetzt war, befand sich in TypeScript (der Superset von JavaScript), und es sollte die Methode des TypsSkripts außerhalb dieser Methode und nicht in dieser Methode gestalten. Nachdem ich es benutzt hatte, wurde mir plötzlich klar, dass Lambda kein schweres neues Merkmal von JDK8 ist? Also hatte ich das Gefühl, dass ich die relevanten Informationen überprüft und sie aufgezeichnet habe:
1. Verhaltensparameterisierung
Kurz gesagt, Verhaltensparametrisierung bedeutet, dass der Körper der Funktion nur einen vorlagenähnlichen allgemeinen Code enthält, während eine Logik, die sich mit dem Geschäftsszenario ändert, in Form von Parametern in die Funktion übergeben wird. Die Verwendung der Verhaltensparametrisierung kann das Programm allgemeiner machen, um die Bedürfnisse häufiger Änderungen zu bewältigen.
Betrachten Sie ein Geschäftsszenario unter der Annahme, dass wir Apple durch ein Programm filtern müssen. Wir definieren zunächst eine Apple -Einheit:
öffentliche Klasse Apple {/** Nummer*/private long id;/** Farbe*/private Farbe Farbe;/** Gewicht*/privates Schwimmergewicht;/** Ursprung*/privater String -Ursprung; public Apple () {} public Apple (lange ID, Farbfarbe, Float -Gewicht, String -Ursprung) {this.id = id;Die anfängliche Nachfrage von Benutzern kann einfach darin bestehen, grüne Äpfel durch das Programm herauszufiltern, damit wir sie schnell über das Programm implementieren können:
öffentliche statische Liste <Apfel> filterGreenApples (Liste <Apfel> apples) {List <Apple> filterapples = new ArrayList <> (); Für (endgültige Apple Apple: apples) {if (color.green.equals (Apple.GetColor ())) {FilterApples.add (Apple);Dieser Code ist einfach und nichts, was es wert ist, gesagt zu werden. Wenn der Benutzer jedoch grün wird, scheint es einfach zu ändern, dass das Ändern des Codes einfach ist, als das Grün des Urteilszustands in Rot zu ändern. Aber wir müssen ein anderes Problem berücksichtigen. Wenn sich die sich ändernden Bedingungen häufig ändern, wird dies getan? Wenn es sich nur um eine Farbänderung handelt, können wir den Benutzer direkt unter den Farburteilsbedingungen übergeben lassen, und die Parameter der Urteilsmethode ändern "die zu beurteilte und die zu filterne Farbe". Aber was ist, wenn der Benutzer nicht nur die Farbe beurteilt, sondern auch Gewicht, Größe usw. beurteilen möchte? Denken Sie, wir können nur verschiedene Parameter hinzufügen, um das Urteil zu vervollständigen? Aber ist es wirklich gut, solche Parameter zu übergeben? Wenn es immer mehr Filterbedingungen gibt und der Kombinationsmodus immer komplexer wird, müssen wir alle Situationen berücksichtigen und entsprechende Bewältigungsstrategien für jede Situation haben? Zu diesem Zeitpunkt können wir das Verhalten parametrisieren, die Filterbedingungen extrahieren und sie als Parameter übergeben. Zu diesem Zeitpunkt können wir eine Urteilsschnittstelle zusammenfassen:
öffentliche Schnittstelle AppleFilter {/*** Filter Abstract ** @param Apple* @return*/boolean Accept (Apple Apple);}/*** Filter in die Schnittstelle einkapseln ArrayList <> (); für (endgültige Apple Apple: Äpfel) {if (filter.accept (Apple)) {filterapples.add (Apple);}} Rückgabefilterapples;}Nach der Abstraking des obigen Verhaltens können wir Filterbedingungen im spezifischen Aufruf einstellen und die Bedingungen als Parameter in die Methode übergeben. Zu diesem Zeitpunkt verwenden wir die Methode der anonymen inneren Klasse:
public static void main (string [] args) {list <Apple> apples = new ArrayList <> (); // Filter Apple List <Apfel> Filterapples = FilterapplePlesByAppleFilter (Äpfel, neue Applefilter () {@Overridepublic boolean Accept (Apple Apple) {// Filter Red rot rots applles applles applles applles applles apples applles tecring uples uples tecring uples uples uples uples uples usiger als 100Greta. Apple.getWeight ()> 100;}});}Dieses Design wird häufig in JDK verwendet, wie z. Aus dem obigen Codeblock ist es jedoch nicht präzise genug. In Java8 können wir es durch Lambda vereinfachen:
// Filter Apple List <Apple> Filterapples = FilterappllesByAppleFilter (Apples, (Apple Apple) -> color.red.equals (Apple.getColor ()) && Apple.getWeight ()> = 100); // () -> xxx () ist die Methodenparameter, und xxx ist die Methode Implementierung ist die Methode Implementierung ist die Methode Implementierung ist die Methode Implementierung ist die Methode Implementierung ist die Methode Implementierung ist die Methode Implementierung ist die Methode implementiert
2. Definition von Lambda Expression
Wir können einen Lambda -Ausdruck als prägnante und passable anonyme Funktion definieren. Zunächst müssen wir klarstellen, dass der Lambda -Ausdruck im Wesentlichen eine Funktion ist. Obwohl es nicht zu einer bestimmten Klasse gehört, verfügt es über eine Parameterliste, einen Funktionskörper, einen Rückgabetyp und die Fähigkeit, Ausnahmen zu veröffentlichen. Zweitens ist es anonym und der Lambda -Ausdruck hat keinen bestimmten Funktionsnamen. Der Lambda -Ausdruck kann wie Parameter übergeben werden, wodurch das Schreiben von Code erheblich vereinfacht wird. Die Formatdefinition lautet wie folgt:
Format 1: Parameterliste -> Ausdruck
Format 2: Parameterliste -> {Expressionssammlung}
Es ist zu beachten, dass der Lambda -Ausdruck das Rückgabe -Schlüsselwort impliziert. In einem einzelnen Ausdruck müssen wir das Rückgabe -Schlüsselwort nicht explizit schreiben. Wenn der Ausdruck jedoch eine Sammlung von Anweisungen ist, müssen wir die Rückgabe explizit hinzufügen und mehrere Ausdrücke mit lockigen Klammern {} einschließen. Sehen wir uns unten einige Beispiele an:
// Die Länge der angegebenen Zeichenfolge zurückgeben, implizit zurückgeben (String S) -> sength () // Geben Sie die nicht armumentierte Methode immer zurück () () -> 42 // Enthält mehrere Ausdruckszeilen, die in lockigen Klammern eingeschlossen sind (int x, int y) -> {int z = x * y; return x + Z;3.. Verwenden Sie Lambda -Ausdrücke basierend auf funktionalen Schnittstellen
Die Verwendung von Lambda -Ausdrücken erfordert die Hilfe von funktionalen Schnittstellen, was bedeutet, dass wir sie nur dann mit Lambda -Ausdrücken vereinfachen können.
Benutzerdefinierte funktionale Schnittstelle:
Funktionale Schnittstellen werden als Schnittstellen definiert, die nur eine abstrakte Methode haben. Die Verbesserung der Schnittstellendefinition von Java8 besteht darin, Standardmethoden einzuführen, damit wir Standardimplementierungen von Methoden in der Schnittstelle bereitstellen können. Unabhängig davon, wie viele Standardmethoden vorhanden sind, so lange wie eine abstrakte Methode, handelt es sich wie folgt wie folgt (siehe oben auf den oben genannten Applefilter):
/*** Apple Filter Interface*/ @functionalInterfacepublic -Schnittstelle AppleFilter {/*** Filterbedingung Abstract ** @param Apple* @return*/boolean Accept (Apple Apple);}AppleFilter enthält nur eine abstrakte Methode Akzeptanz (Apple Apple). Gemäß der Definition kann es als funktionale Schnittstelle angesehen werden. Beim Definieren fügen wir der Schnittstelle die Annotation @FunctionalInterface hinzu, um die Schnittstelle als funktionale Schnittstelle zu markieren. Diese Schnittstelle ist jedoch optional. Nach dem Hinzufügen dieser Schnittstelle schränkt der Compiler die Schnittstelle auf nur eine abstrakte Methode ein. Andernfalls wird ein Fehler gemeldet. Es wird empfohlen, diese Annotation zur Funktionsschnittstelle hinzuzufügen.
JDK wird mit funktionaler Schnittstelle geliefert:
JDK ist ein Lambda -Ausdruck mit reichen funktionellen Schnittstellen. Im Folgenden finden Sie Beispiele für die Verwendung von Prädikat <t>, Verbraucher <t>, Funktion <t, r>.
Prädikat:
@FunctionalInterfacepublic Interface Predicate <T> {/*** Bewertet dieses Vorhersage im angegebenen Argument.Die Funktion des Prädikats ähnelt dem obigen Applefilter. Es verwendet die Bedingungen, die wir extern festgelegt haben, um die eingehenden Parameter zu überprüfen, und gibt den Booleschen Verifizierungsergebnis zurück. Im Folgenden wird das Prädikat verwendet, um die Elemente der Listensammlung zu filtern:
/**** @param list* @param predicate* @param <t>* @return*/public <T> List <T> Filter (Liste <T> List, Predicate <T> Prädikat) {list <T> newList = new ArrayList <T> (); für (endgültige t: list) {if (Predicate.Test (t) {NewList.add (t:}verwenden:
Demo.filter (Liste, (String Str) -> null! = str &&! str.isempty ());
Verbraucher
@FunctionalInterfacepublic Interface Consumer <T> {/*** führt diese Operation im angegebenen Argument aus. ** @param t Das Eingabemargument*/void Accept (t t);}Der Verbraucher liefert eine abstrakte Akzeptanzfunktion, die Parameter empfängt, aber keine Werte zurückgibt. Im Folgenden wird der Verbraucher verwendet, um die Sammlung zu durchqueren.
/*** Durchqueren der Sammlung und führen Sie benutzerdefiniertes Verhalten durch ** @paramliste* @param Consumer* @param <t>*/public <t> void Filter (Liste <T> Liste, Verbraucher <T> Verbraucher) {für (endgültige t t: list) {Consumer.accept (t);}}}}}}}}}}}}}}}}}Durch die obige funktionale Schnittstelle können Sie die String-Sammlung iterieren und nicht leere Zeichenfolgen drucken:
Demo.filter (Liste, (String Str) -> {if (stringutils.isnotblank (str)) {System.out.println (str);}});Funktion
@FunctionalInterfacepublic -Schnittstellenfunktion <t, r> {/*** Anwendet diese Funktion auf das angegebene Argument.Funktion führt einen Konvertierungsvorgang durch. Die Eingabe ist Daten vom Typ T und gibt Daten vom Typ R. zurück. Im Folgenden wird die Funktion zum Konvertieren des Satzes verwendet:
public <T, r> list <r> filter (Liste <T> List, Funktion <T, r> Funktion) {List <R> newList = new ArrayList <R> (); für (endgültige t t: list) {newList.add (function.apply (t));} return NewList;} zurückgeben;}andere:
Demo.filter (Liste, (String Str) -> Integer.ParseInt (str));
Die obigen funktionalen Schnittstellen liefern auch einige Standardimplementierungen logischer Vorgänge. Sprechen wir später darüber, wenn Sie die Standardmethoden der Java8 -Schnittstelle einführen ~
Einige Dinge, auf die Sie während der Verwendung achten sollten:
Geben Sie Inferenz ein:
Während des Codierungsprozesses fragen wir uns manchmal, welche funktionale Schnittstelle unser aufrufender Code übereinstimmt. Tatsächlich füllt der Compiler korrekte Urteile auf der Grundlage von Parametern, Rückgabetyp, Ausnahmetyp (falls vorhanden) usw.
Wenn Sie auf bestimmte Weise aufrufen, kann der Parametertyp manchmal weggelassen werden, wodurch der Code weiter vereinfacht wird:
// Filter Apple List <Apple> Filterapples = FilterapplplesByAppleFilter (Äpfel, (Apple Apple) -> color.red.Equals (Apple.getColor ()) && Apple.GetWeight ()> = 100); // In einigen Fällen können wir sogar Parametertypen weglassen und der Compiler -Apply -Apply -Appling (Apple -Apply apply apply apply> filterapples = filterapples = filterapples = filterapies = filterapples = filterapies = filterapies = filterapies = filterapies Color.red.equals (Apple.getColor ()) && Apple.getWeight ()> = 100);
Lokale Variablen
Alle Beispiele über unseren Lambda -Ausdrücken verwenden ihre Körperparameter. Wir können auch lokale Variablen in Lambda wie folgt verwenden
Int Gewicht = 100; LIST <Apfel> filterapples = filterappllesByAppleFilter (apples, Apple -> color.red.equals (Apple.getColor ()) && Apple.getWeight ()> = Gewicht) ;:
In diesem Beispiel verwenden wir das lokale variable Gewicht in der Lambda. Die Verwendung lokaler Variablen in der Lambda muss jedoch verlangen, dass die Variable explizit als endgültig oder tatsächlich endgültig deklariert wird. Dies liegt hauptsächlich daran, dass die lokale Variable auf dem Stapel gespeichert ist und der Lambda -Ausdruck in einem anderen Thread ausgeführt wird. Wenn die Thread -Ansicht auf die lokale Variable zugreift, kann die Variable geändert oder recycelt werden, sodass nach der Änderung keine Sicherheitsprobleme mit Fadensicherheit mit endgültigem Zustand sind.
Iv. Methode Zitat
Mithilfe von Methodenreferenzen können der Code vereinfacht werden. Manchmal lässt diese Vereinfachung den Code intuitiver aussehen. Schauen wir uns ein Beispiel an:
/* ... den Initialisierungsbetrieb von Äpfeln weglassen
Methodenreferenzen verbinden die Methodenmitgliedschaft und Methode selbst durch ::, die hauptsächlich in drei Kategorien unterteilt sind:
Statische Methode
(args) -> className.staticMethod (args)
Konvertieren zu
Klassenname :: staticMethod
Beispielmethode des Parameters
(args) -> args.instancemethod ()
Konvertieren zu
ClassName :: Instancemethod // className ist type args
Externe Instanzmethode
(args) -> ext.instancemethod (args)
Konvertieren zu
ext :: Instancemethod (Args)
Siehe:
http://www.codeceo.com/article/lambda-of-java-8.html
Das obige ist der Lambda -Ausdruck der neuen JDK8 -Funktion, die der Editor Ihnen vorgestellt hat. Ich hoffe, es wird Ihnen hilfreich sein. Wenn Sie Fragen haben, hinterlassen Sie mir bitte eine Nachricht und der Editor wird Ihnen rechtzeitig antworten. Vielen Dank für Ihre Unterstützung auf der Wulin.com -Website!