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

Java Lambda Expressions meistern: Von Grundlagen bis Stream API

Java Lambda Expressions meistern

Erkunden Sie Javas Lambda-Ausdrücke, funktionale Interfaces, Generics und die Stream API mit klaren Beispielen.

Java 8 führte Lambda-Ausdrücke ein, um die Ausdruckskraft der Sprache zu erhöhen und Entwicklern zu ermöglichen, prägnanteren und lesbareren Code zu schreiben.

Bevor Sie in Lambdas eintauchen, ist es essenziell, funktionale Interfaces zu verstehen, das Rückgrat der Lambda-Implementierung.

Was ist ein funktionales Interface?

Ein funktionales Interface ist ein Java-Interface, das genau eine abstrakte Methode enthält. Diese einzelne Methode definiert den beabsichtigten Zweck des Interfaces.

Das Runnable Interface aus java.lang ist ein klassisches Beispiel, das nur die run() Methode exponiert.

Beispiel 1: Funktionales Interface definieren

import java.lang.FunctionalInterface;

@FunctionalInterface
public interface MyInterface {
    // Einzige abstrakte Methode
    double getValue();
}

Hier ist MyInterface mit @FunctionalInterface annotiert, was den Compiler zwingt, den funktionalen Interface-Vertrag durchzusetzen und die versehentliche Hinzufügung mehrerer abstrakter Methoden zu verhindern. Die Annotation ist optional, aber sehr empfohlen für Klarheit und Sicherheit.

In Java 7 wurden funktionale Interfaces als Single Abstract Methods (SAMs) bezeichnet und typischerweise mit anonymen Klassen implementiert.

Beispiel 2: SAM mit anonymer Klasse implementieren

public class FunctionInterfaceTest {
    public static void main(String[] args) {
        // Anonyme Klasse implementiert Runnable
        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.

Während anonyme Classes Boilerplate im Vergleich zu traditionellen Implementierungen reduzieren, bleibt die Syntax verbose. Lambda-Ausdrücke eliminieren die Notwendigkeit expliziter Methodennamen beim Übergeben funktionaler Interfaces als Argumente.


Einführung in Lambda-Ausdrücke

Ein Lambda-Ausdruck ist im Wesentlichen eine anonyme Methode, die eine prägnante Implementierung der abstrakten Methode eines funktionalen Interfaces bereitstellt. Er führt nicht unabhängig aus; stattdessen liefert er das Verhalten für die Methode des Interfaces.

Wie man einen Lambda-Ausdruck in Java definiert

Die allgemeine Syntax ist:

(parameter list) -> lambda body

->) trennt die Parameterliste vom Body. Unten sind konkrete Beispiele.

Angenommen, wir haben eine Methode, die Pi zurückgibt:

double getPiValue() { return 3.1415; }

Mit einem Lambda:

() -> 3.1415

Ohne Parameter ist die linke Seite des Pfeils leer, und die rechte Seite ist der Expression-Body, der den Wert zurückgibt.


Arten von Lambda-Bodys

Java Lambda-Bodys gibt es in zwei Formen:

1. Expression Body – enthält einen einzelnen Ausdruck.

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

2. Block Body – in Klammern gekapselt, erlaubt mehrere Statements und optionales return.

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

Hinweis: Expression Bodies benötigen kein explizites return, Block Bodies tun dies, wenn ein Wert zurückgegeben wird.


Beispiel 3: Lambda-Ausdruck in der Praxis

Lassen Sie uns ein Java-Programm schreiben, das Pi mit einem Lambda-Ausdruck zurückgibt.

import java.lang.FunctionalInterface;

@FunctionalInterface
interface MyInterface {
    double getPiValue();
}

public class Main {
    public static void main(String[] args) {
        MyInterface ref = () -> 3.1415;
        System.out.println("Value of Pi = " + ref.getPiValue());
    }
}

Ausgabe:

Value of Pi = 3.1415

Wichtige Erkenntnisse:


Lambda-Ausdrücke mit Parametern

Wie Methoden können Lambdas Parameter akzeptieren. Beispiel:

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

Dieses Lambda prüft, ob die eingehende Ganzzahl gerade ist.

Beispiel 4: String mit parameterisiertem Lambda umkehren


@FunctionalInterface
interface MyInterface {
    String reverse(String s);
}

public class Main {
    public static void main(String[] args) {
        MyInterface ref = (str) -> {
            String result = "";
            for (int i = str.length() - 1; i >= 0; i--) {
                result += str.charAt(i);
            }
            return result;
        };
        System.out.println("Lambda reversed = " + ref.reverse("Lambda"));
    }
}

Ausgabe:

Lambda reversed = adbmaL

Generisches funktionales Interface

Funktionale Interfaces können generisch sein, was ihnen erlaubt, auf jedem Datentyp zu operieren. Zum Beispiel:


@FunctionalInterface
interface MyInterface<T> {
    T func(T t);
}

Beispiel 5: Generische Lambdas für Strings und Integers


public class Main {
    public static void main(String[] args) {
        // String Umkehrung
        MyInterface<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"));

        // Integer Fakultät
        MyInterface<Integer> factorial = (n) -> {
            int result = 1;
            for (int i = 1; i <= n; i++) {
                result *= i;
            }
            return result;
        };
        System.out.println("factorial of 5 = " + factorial.func(5));
    }
}

Ausgabe:

Lambda reversed = adbmaL
factorial of 5 = 120

Lambda-Ausdrücke und die Stream API

Das java.util.stream Paket, eingeführt in JDK 8, ermächtigt Entwickler, funktionale Operationen auf Collections durchzuführen: Filtern, Mapping, Reduzieren, Sortieren und mehr.

Betrachten Sie eine Liste von Ortsnamen, jeder mit seinem Land präfixiert. Mit Streams und Lambdas können wir Daten effizient extrahieren und manipulieren.

Beispiel 6: Stream-Verarbeitung mit Lambdas


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

public class StreamMain {
    static List<String> places = new ArrayList<>();

    public static List<String> getPlaces() {
        places.add("Nepa, Kathmandu");
        places.add("Nepa, 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("Orte aus Nepal:");
        myPlaces.stream()
            .filter(p -> p.startsWith("Nepa"))
            .map(p -> p.toUpperCase())
            .sorted()
            .forEach(p -> System.out.println(p));
    }
}

Ausgabe:

Orte aus Nepal:
NEPA, KATHMANDU
NEPA, POKHARA

Hier reduziert die Kette von Stream-Operationen – filter, map, sorted, forEach – jeweils einen Lambda annehmend, den Boilerplate drastisch im Vergleich zu Pre-Java-8-Lösungen.

Java

  1. C#-Interfaces meistern: Definition, Implementierung und praktische Anwendungsfälle
  2. Java Operatoren meistern: Typen, Syntax und praktische Beispiele
  3. Java Ausdrücke, Anweisungen und Blöcke verstehen
  4. Java-Schnittstellen meistern: Konzepte, Implementierung und Best Practices
  5. Java Try-With-Resources meistern: Automatisches Ressourcenmanagement erklärt
  6. Java Annotations erklärt: Typen, Platzierung und praktische Beispiele
  7. Interface vs. Abstrakte Klasse in Java: Die richtige Abstraktion wählen
  8. Java Reguläre Ausdrücke: Pattern Matching mit java.util.regex meistern
  9. Java Interfaces verstehen: Definitionen, Verwendung und Best Practices
  10. Java 9 Private Interface Methods: Bessere Kapselung & Code-Wiederverwendung