Industrielle Fertigung
Industrielles Internet der Dinge | Industrielle Materialien | Gerätewartung und Reparatur | Industrielle Programmierung |
home  MfgRobots >> Industrielle Fertigung >  >> Industrial programming >> Java

Java-Lambda-Ausdrücke

Java-Lambda-Ausdrücke

In diesem Artikel erfahren wir anhand von Beispielen mehr über Java-Lambda-Ausdrücke und die Verwendung von Lambda-Ausdrücken mit funktionalen Schnittstellen, generischen funktionalen Schnittstellen und Stream-API.

Der Lambda-Ausdruck wurde erstmals in Java 8 eingeführt. Sein Hauptziel ist es, die Ausdruckskraft der Sprache zu erhöhen.

Aber bevor wir uns mit Lambdas befassen, müssen wir zuerst funktionale Schnittstellen verstehen.


Was ist eine funktionale Schnittstelle?

Wenn eine Java-Schnittstelle genau eine abstrakte Methode enthält, wird sie als funktionale Schnittstelle bezeichnet. Diese einzige Methode gibt den Verwendungszweck der Schnittstelle an.

Zum Beispiel Runnable Schnittstelle aus Paket java.lang; ist eine funktionale Schnittstelle, weil sie nur eine Methode darstellt, d. h. run() .

Beispiel 1:Definieren Sie eine funktionale Schnittstelle in Java

import java.lang.FunctionalInterface;
@FunctionalInterface
public interface MyInterface{
    // the single abstract method
    double getValue();
}

Im obigen Beispiel hat das Interface MyInterface nur eine abstrakte Methode getValue(). Daher ist es eine funktionale Schnittstelle.

Hier haben wir die Anmerkung @FunctionalInterface verwendet . Die Annotation zwingt den Java-Compiler anzugeben, dass die Schnittstelle eine funktionale Schnittstelle ist. Daher darf nicht mehr als eine abstrakte Methode verwendet werden. Es ist jedoch nicht obligatorisch.

In Java 7 wurden funktionale Schnittstellen als Single Abstract Methods oder SAM betrachtet Typ. SAMs wurden üblicherweise mit anonymen Klassen in Java 7 implementiert.

Beispiel 2:Implementieren Sie SAM mit anonymen Klassen in Java

public class FunctionInterfaceTest {
    public static void main(String[] args) {

        // anonymous class
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("I just implemented the Runnable Functional Interface.");
            }
        }).start();
    }
}

Ausgabe :

I just implemented the Runnable Functional Interface.

Hier können wir eine anonyme Klasse an eine Methode übergeben. Dies hilft beim Schreiben von Programmen mit weniger Code in Java 7. Die Syntax war jedoch immer noch schwierig und es waren viele zusätzliche Codezeilen erforderlich.

Java 8 erweiterte die Leistungsfähigkeit eines SAMs, indem es noch einen Schritt weiter ging. Da wir wissen, dass eine funktionale Schnittstelle nur eine Methode hat, sollte es nicht nötig sein, den Namen dieser Methode zu definieren, wenn sie als Argument übergeben wird. Mit dem Lambda-Ausdruck können wir genau das tun.


Einführung in Lambda-Ausdrücke

Der Lambda-Ausdruck ist im Wesentlichen eine anonyme oder unbenannte Methode. Der Lambda-Ausdruck wird nicht alleine ausgeführt. Stattdessen wird es verwendet, um eine Methode zu implementieren, die durch eine funktionale Schnittstelle definiert ist.

Wie definiere ich einen Lambda-Ausdruck in Java?

So können wir Lambda-Ausdrücke in Java definieren.

(parameter list) -> lambda body

Der neue Operator (-> ) wird als Pfeiloperator oder Lambdaoperator bezeichnet. Die Syntax ist im Moment möglicherweise nicht klar. Sehen wir uns einige Beispiele an,

Angenommen, wir haben eine Methode wie diese:

double getPiValue() {
    return 3.1415;
}

Wir können diese Methode mit dem Lambda-Ausdruck schreiben als:

() -> 3.1415

Hier hat die Methode keine Parameter. Daher enthält die linke Seite des Operators einen leeren Parameter. Die rechte Seite ist der Lambda-Körper, der die Aktion des Lambda-Ausdrucks angibt. In diesem Fall gibt es den Wert 3.1415 zurück.


Arten von Lambda-Körpern

In Java gibt es zwei Arten von Lambda-Body.

1. Ein Körper mit einem einzigen Ausdruck

() -> System.out.println("Lambdas are great");

Diese Art von Lambda-Körper wird als Ausdruckskörper bezeichnet.

2. Ein Körper, der aus einem Codeblock besteht.

() -> {
    double pi = 3.1415;
    return pi;
};

Diese Art des Lambda-Körpers ist als Blockkörper bekannt. Der Blockkörper ermöglicht es dem Lambda-Körper, mehrere Anweisungen einzuschließen. Diese Anweisungen sind in geschweiften Klammern eingeschlossen und Sie müssen nach den geschweiften Klammern ein Semikolon hinzufügen.

Hinweis :Für den Blockkörper können Sie eine return-Anweisung haben, wenn der Körper einen Wert zurückgibt. Der Ausdruckskörper erfordert jedoch keine return-Anweisung.


Beispiel 3:Lambda-Ausdruck

Lassen Sie uns ein Java-Programm schreiben, das den Wert von Pi mithilfe des Lambda-Ausdrucks zurückgibt.

Wie bereits erwähnt, wird ein Lambda-Ausdruck nicht alleine ausgeführt. Vielmehr bildet es die Implementierung der abstrakten Methode, die durch die funktionale Schnittstelle definiert ist.

Also müssen wir zuerst eine funktionale Schnittstelle definieren.

import java.lang.FunctionalInterface;

// this is functional interface
@FunctionalInterface
interface MyInterface{

    // abstract method
    double getPiValue();
}

public class Main {

    public static void main( String[] args ) {

    // declare a reference to MyInterface
    MyInterface ref;
    
    // lambda expression
    ref = () -> 3.1415;
    
    System.out.println("Value of Pi = " + ref.getPiValue());
    } 
}

Ausgabe :

Value of Pi = 3.1415

Im obigen Beispiel


Lambda-Ausdrücke mit Parametern

Bisher haben wir Lambda-Ausdrücke ohne Parameter erstellt. Ähnlich wie Methoden können Lambda-Ausdrücke jedoch auch Parameter haben. Zum Beispiel

(n) -> (n%2)==0

Hier ist die Variable n in der Klammer ein Parameter, der an den Lambda-Ausdruck übergeben wird. Der Lambda-Körper nimmt den Parameter und prüft, ob er gerade oder ungerade ist.

Beispiel 4:Lambda-Ausdruck mit Parametern verwenden

@FunctionalInterface
interface MyInterface {

    // abstract method
    String reverse(String n);
}

public class Main {

    public static void main( String[] args ) {

        // declare a reference to MyInterface
        // assign a lambda expression to the reference
        MyInterface ref = (str) -> {

            String result = "";
            for (int i = str.length()-1; i >= 0 ; i--)
            result += str.charAt(i);
            return result;
        };

        // call the method of the interface
        System.out.println("Lambda reversed = " + ref.reverse("Lambda"));
    }

}

Ausgabe :

Lambda reversed = adbmaL

Generische Funktionsschnittstelle

Bisher haben wir die funktionale Schnittstelle verwendet, die nur einen Werttyp akzeptiert. Zum Beispiel

@FunctionalInterface
interface MyInterface {
    String reverseString(String n);
}

Die obige funktionale Schnittstelle akzeptiert nur String und gibt String zurück . Wir können die funktionale Schnittstelle jedoch generisch machen, sodass jeder Datentyp akzeptiert wird. Wenn Sie sich bei Generika nicht sicher sind, besuchen Sie Java Generics.

Beispiel 5:Generische funktionale Schnittstelle und Lambda-Ausdrücke

// GenericInterface.java
@FunctionalInterface
interface GenericInterface<T> {

    // generic method
    T func(T t);
}

// GenericLambda.java
public class Main {

    public static void main( String[] args ) {

        // declare a reference to GenericInterface
        // the GenericInterface operates on String data
        // assign a lambda expression to it
        GenericInterface<String> reverse = (str) -> {

            String result = "";
            for (int i = str.length()-1; i >= 0 ; i--)
            result += str.charAt(i);
            return result;
        };

        System.out.println("Lambda reversed = " + reverse.func("Lambda"));

        // declare another reference to GenericInterface
        // the GenericInterface operates on Integer data
        // assign a lambda expression to it
        GenericInterface<Integer> factorial = (n) -> {

            int result = 1;
            for (int i = 1; i <= n; i++)
            result = i * result;
            return result;
        };

        System.out.println("factorial of 5 = " + factorial.func(5));
    }
}

Ausgabe :

Lambda reversed = adbmaL
factorial of 5 = 120

Im obigen Beispiel haben wir eine generische funktionale Schnittstelle mit dem Namen GenericInterface erstellt . Es enthält eine generische Methode namens func() .

Hier, innerhalb der Hauptklasse,


Lambda-Ausdruck und Stream-API

Das neue java.util.stream-Paket wurde zu JDK8 hinzugefügt, das es Java-Entwicklern ermöglicht, Operationen wie Suchen, Filtern, Zuordnen, Reduzieren oder Bearbeiten von Sammlungen wie Lists durchzuführen .

Zum Beispiel haben wir einen Datenstrom (in unserem Fall ein List von String ), wobei jede Zeichenfolge eine Kombination aus Ländername und Ort des Landes ist. Jetzt können wir diesen Datenstrom verarbeiten und nur die Orte aus Nepal abrufen.

Dazu können wir Massenoperationen im Stream durch die Kombination von Stream-API und Lambda-Ausdruck durchführen.

Beispiel 6:Demonstration der Verwendung von Lambdas mit der Stream-API

import java.util.ArrayList;
import java.util.List;

public class StreamMain {

    // create an object of list using ArrayList
    static List<String> places = new ArrayList<>();

    // preparing our data
    public static List getPlaces(){

        // add places and country to the list
        places.add("Nepal, Kathmandu");
        places.add("Nepal, Pokhara");
        places.add("India, Delhi");
        places.add("USA, New York");
        places.add("Africa, Nigeria");

        return places;
    }

    public static void main( String[] args ) {

        List<String> myPlaces = getPlaces();
        System.out.println("Places from Nepal:");
        
        // Filter places from Nepal
        myPlaces.stream()
                .filter((p) -> p.startsWith("Nepal"))
                .map((p) -> p.toUpperCase())
                .sorted()
                .forEach((p) -> System.out.println(p));
    }

}

Ausgabe :

Places from Nepal:
NEPAL, KATHMANDU
NEPAL, POKHARA

Beachten Sie im obigen Beispiel die Anweisung,

myPlaces.stream()
        .filter((p) -> p.startsWith("Nepal"))
        .map((p) -> p.toUpperCase())
        .sorted()
        .forEach((p) -> System.out.println(p));

Hier verwenden wir Methoden wie filter() , map() und forEach() der Stream-API. Diese Methoden können einen Lambda-Ausdruck als Eingabe annehmen.

Wir können auch unsere eigenen Ausdrücke basierend auf der oben gelernten Syntax definieren. Dadurch können wir die Codezeilen drastisch reduzieren, wie wir im obigen Beispiel gesehen haben.


Java

  1. C#-Schnittstelle
  2. Java-Operatoren
  3. Java-Ausdrücke, -Anweisungen und -Blöcke
  4. Java-Schnittstelle
  5. Java-Versuch-mit-Ressourcen
  6. Java-Anmerkungen
  7. Schnittstelle vs. abstrakte Klasse in Java:Was ist der Unterschied?
  8. Java - Reguläre Ausdrücke
  9. Java - Schnittstellen
  10. Java 9 - Private Schnittstellenmethoden