Verwenden Sie Lambda-Ausdrücke, um die Lesbarkeit und Wartbarkeit von Java-Code zu verbessern

Einführung

Java ist eine leistungsstarke Programmiersprache, die umfangreiche Funktionen und APIs bietet, um verschiedene Arten von Anwendungsanforderungen zu erfüllen. In der tatsächlichen Entwicklung stellen wir jedoch häufig fest, dass der Java-Code zu lang und zu kompliziert ist, um ihn zu verstehen und zu warten. Zu diesem Zeitpunkt müssen wir einige moderne Programmiertechniken und -methoden verwenden, um die Lesbarkeit und Wartbarkeit des Codes zu verbessern. Der Lambda-Ausdruck ist eine neue Funktion, die von Java 8 eingeführt wurde und uns dabei helfen kann, Code zu vereinfachen und die Entwicklungseffizienz zu verbessern. In diesem Artikel werden die Prinzipien, die Verwendung und Best Practices von Lambda-Ausdrücken vorgestellt, um Ihnen dabei zu helfen, Lambda-Ausdrücke besser anzuwenden und die Lesbarkeit und Wartbarkeit von Java-Code zu verbessern.

1. Das Grundprinzip des Lambda-Ausdrucks

Vor Java 8 verwenden wir normalerweise anonyme innere Klassen, um funktionale Programmierung zu implementieren. Eine anonyme innere Klasse ist eine leichtgewichtige Klassendefinition, die normalerweise zum Erstellen einer Klasseninstanz mit nur einer Methode verwendet wird. Der folgende Code erstellt beispielsweise eine anonyme innere Klasse, die die Comparator-Schnittstelle zum Sortieren von Zeichenfolgen nach Länge implementiert:

List<String> list = Arrays.asList("aaa", "bb", "c");
Collections.sort(list, new Comparator<String>() {
    public int compare(String s1, String s2) {
        return Integer.compare(s1.length(), s2.length());
    }
});

Die Logik dieses Codes besteht darin, die Längen der Zeichenfolgen zu vergleichen und sie in aufsteigender Reihenfolge der Länge zu sortieren. Unter anderem definiert die Comparator-Schnittstelle eine Vergleichsmethode zum Vergleichen der Größe zweier Objekte. Die anonyme innere Klasse implementiert diese Schnittstelle und überschreibt die Vergleichsmethode zur einfacheren Sortierung.

Allerdings hat diese Notation einige Nachteile. Erstens ist die Syntax anonymer innerer Klassen langwierig und kompliziert, was leicht zu einer schlechten Lesbarkeit des Codes führen kann. Zweitens ist eine anonyme innere Klasse normalerweise nur ein syntaktischer Zucker, sie kapselt den Code nicht wirklich in eine Funktion. Das bedeutet, dass wir keine Parametrisierungs-, Kompositions- usw. Operationen an anonymen inneren Klassen wie gewöhnlichen Funktionen durchführen können.

Die Entstehung von Lambda-Ausdrücken soll diese Probleme lösen. Ein Lambda-Ausdruck kann als anonyme Funktion betrachtet werden, die keine Klassendefinition erfordert und direkt durch eine Anweisung dargestellt wird. Beispielsweise können wir Lambda-Ausdrücke verwenden, um den obigen Code zu implementieren:

List<String> list = Arrays.asList("aaa", "bb", "c");
Collections.sort(list, (s1, s2) -> Integer.compare(s1.length(), s2.length()));

Die Logik dieses Codes ist dieselbe wie die des vorherigen Codes, außer dass ein Lambda-Ausdruck verwendet wird, um die Definition der Vergleichsfunktion zu vereinfachen. Darunter stellt eine Funktion ​(s1, s2) -> Integer.compare(s1.length(), s2.length())​dar , die zwei Parameter s1 und s2 akzeptiert und das Vergleichsergebnis ihrer Längen zurückgibt.

Die Syntax eines Lambda-Ausdrucks besteht aus drei Teilen: der Parameterliste, der Pfeilnotation und dem Funktionskörper . Darunter definieren die Parameterliste und das Pfeilsymbol die Eingabe des Lambda-Ausdrucks, und der Funktionskörper definiert die Ausgabe des Lambda-Ausdrucks. Der Typ des Lambda-Ausdrucks wird durch seinen Kontext bestimmt. Im obigen Beispiel ist der Typ des Lambda-Ausdrucks Comparator<String>, da er an die Collections.sort-Methode übergeben wird.

Ein weiterer Vorteil von Lambda-Ausdrücken besteht darin, dass damit einige zusammengesetzte Vorgänge wie Kombinationen, Filterungen, Zuordnungen usw. ausgeführt werden können. Beispielsweise können wir mithilfe von Lambda-Ausdrücken eine Liste von Zeichenfolgen filtern und zuordnen:

List<String> list = Arrays.asList("aaa", "bb", "c");
List<String> filtered = list.stream()
        .filter(s -> s.length() > 1)
        .map(s -> s.toUpperCase())
        .collect(Collectors.toList());

Die Logik dieses Codes besteht darin, zuerst die Zeichenfolgen herauszufiltern, deren Länge kleiner oder gleich 1 ist, dann die verbleibenden Zeichenfolgen in Großbuchstaben umzuwandeln und sie in einer neuen Liste zu speichern. Unter diesen konvertiert die Stream-Methode eine Liste in einen Stream, die Filtermethode wird zum Filtern von Elementen verwendet, die Map-Methode wird zum Konvertieren von Elementen in neue Werte verwendet und die Collect-Methode wird zum Sammeln von Elementen im Stream in einer Liste verwendet.

Durch Lambda-Ausdrücke können wir komplexe Vorgänge einfach implementieren, ohne viel langen Code schreiben zu müssen. Im Folgenden stellen wir vor, wie Sie Lambda-Ausdrücke verwenden, um die Lesbarkeit und Wartbarkeit von Java-Code zu verbessern.

2. Verwenden Sie Lambda-Ausdrücke, um die Lesbarkeit und Wartbarkeit von Java-Code zu verbessern

1. Ersetzen Sie die anonyme innere Klasse durch einen Lambda-Ausdruck

Wie bereits erwähnt, können Lambda-Ausdrücke Code ersetzen, der anonyme innere Klassen verwendet. Die Verwendung von Lambda-Ausdrücken kann die Codemenge reduzieren und den Code prägnanter und verständlicher machen. Der folgende Code verwendet beispielsweise eine anonyme innere Klasse, um einen Thread zu erstellen:

new Thread(new Runnable() {
    public void run() {
        System.out.println("Hello, world!");
    }
}).start();

Wir können Lambda-Ausdrücke verwenden, um anonyme innere Klassen zu ersetzen:

new Thread(() -> System.out.println("Hello, world!")).start();

Die Logik dieses Codes lautet: Erstellen Sie einen neuen Thread, der während der Ausführung eine Nachricht ausgibt. Darunter ​() -> System.out.println("Hello, world!")​stellt es einen Lambda-Ausdruck ohne Parameter dar, dessen Funktionskörper darin besteht, eine Information auszugeben.

2. Verwenden Sie Lambda-Ausdrücke, um Filtervorgänge zu vereinfachen

In Java müssen wir häufig Daten filtern. Normalerweise verwenden wir Schleifen, um die Daten zu durchlaufen, und verwenden if-Anweisungen, um zu überprüfen, ob bestimmte Bedingungen erfüllt sind. Dies kann mithilfe von Lambda-Ausdrücken vereinfacht werden:

List<String> list = Arrays.asList("aaa", "bb", "c");
List<String> filtered = list.stream()
        .filter(s -> s.length() > 2)
        .collect(Collectors.toList());

Die Logik dieses Codes ist dieselbe wie beim vorherigen Code: Filtern Sie eine Zeichenfolge heraus, deren Länge größer als 2 ist, aus einer Zeichenfolgenliste und speichern Sie sie in einer neuen Liste. Darunter stellt ​​​​einen Lambda-Ausdruck mit einem Parameter ​s -> s.length() > 2​dar , und sein Funktionskörper ist ​s.length() > 2​​.

3. Verwenden Sie Lambda-Ausdrücke, um Mapping-Vorgänge zu vereinfachen

Zusätzlich zu Filtervorgängen müssen wir häufig Zuordnungsvorgänge für Daten durchführen. Normalerweise verwenden wir Schleifen, um die Daten zu durchlaufen und verwenden eine Methode, um die Daten in eine neue Form umzuwandeln. Der folgende Code wandelt beispielsweise alle Zeichenfolgen in einer Zeichenfolgenliste in Großbuchstaben um:

List<String> list = Arrays.asList("aaa", "bb", "c");
List<String> mapped = new ArrayList<String>();
for (String s : list) {
    mapped.add(s.toUpperCase());
}

Wir können diesen Vorgang mithilfe von Lambda-Ausdrücken vereinfachen:

List<String> list = Arrays.asList("aaa", "bb", "c");
List<String> mapped = list.stream()
        .map(s -> s.toUpperCase())
        .collect(Collectors.toList());

Die Logik dieses Codes lautet: Konvertieren Sie alle Zeichenfolgen in einer Zeichenfolgenliste in Großbuchstaben und speichern Sie sie in einer neuen Liste. Darunter stellt ​​​​einen Lambda-Ausdruck mit einem Parameter ​s -> s.toUpperCase()​dar , und sein Funktionskörper ist ​s.toUpperCase()​​.

4. Verwenden Sie Lambda-Ausdrücke, um Sortiervorgänge zu vereinfachen

In Java müssen wir häufig Daten sortieren. Normalerweise verwenden wir Sortieralgorithmen, um Daten zu sortieren. Der folgende Code verwendet beispielsweise die Methode „Collections.sort“, um eine Liste von Zeichenfolgen zu sortieren:

List<String> list = Arrays.asList("ccc", "aa", "b");
Collections.sort(list, new Comparator<String>() {
    public int compare(String s1, String s2) {
        return s1.length() - s2.length();
    }
});

Wir können diesen Vorgang mithilfe von Lambda-Ausdrücken vereinfachen:

List<String> list = Arrays.asList("ccc", "aa", "b");
Collections.sort(list, (s1, s2) -> s1.length() - s2.length());

Die Logik dieses Codes ist dieselbe wie beim vorherigen Code: Sortieren Sie eine Liste von Zeichenfolgen, sortiert nach der Länge der Zeichenfolgen. Darunter stellt ​​​​einen Lambda-Ausdruck mit zwei Parametern ​(s1, s2) -> s1.length() - s2.length()​dar , und sein Funktionskörper ist ​s1.length() - s2.length()​​.

5. Verwenden Sie Lambda-Ausdrücke, um Rückruffunktionen zu implementieren

In Java müssen wir häufig Rückruffunktionen verwenden, um bestimmte Funktionen zu erreichen. Normalerweise müssen wir eine Schnittstelle definieren, darin eine Methode implementieren und dann eine Instanz der Implementierungsklasse an eine Methode übergeben, damit die Methode bei Bedarf aufgerufen werden kann. Der folgende Code definiert beispielsweise eine Schnittstelle und eine implementierende Klasse und übergibt eine Instanz der implementierenden Klasse an eine Methode:

interface Callback {
    void call(String message);
}

class MyClass {
    void doSomething(Callback callback) {
        // 做一些事情
        callback.call("完成了");
    }
}

class MyCallback implements Callback {
    public void call(String message) {
        System.out.println("回调函数被调用,消息为:" + message);
    }
}

MyClass myClass = new MyClass();
myClass.doSomething(new MyCallback());

Wir können diesen Vorgang mithilfe von Lambda-Ausdrücken vereinfachen:

interface Callback {
    void call(String message);
}

class MyClass {
    void doSomething(Callback callback) {
        // 做一些事情
        callback.call("完成了");
    }
}

MyClass myClass = new MyClass();
myClass.doSomething(message -> System.out.println("回调函数被调用,消息为:" + message));

6. Verwenden von Lambda-Ausdrücken zum Implementieren von Threads

In Java können wir Threads verwenden, um asynchrone Aufgaben auszuführen. Normalerweise müssen wir eine Klasse definieren und die Runnable-Schnittstelle implementieren, dann eine Instanz dieser Klasse erstellen und sie an den Konstruktor der Thread-Klasse übergeben, um bei Bedarf Threads zu erstellen. Der folgende Code definiert beispielsweise eine Klasse, die die Runnable-Schnittstelle implementiert, erstellt dann eine Instanz dieser Klasse und übergibt sie an den Konstruktor der Thread-Klasse:

class MyRunnable implements Runnable {
    public void run() {
        System.out.println("Hello, World!");
    }
}

Thread thread = new Thread(new MyRunnable());
thread.start();

Wir können diesen Vorgang mithilfe von Lambda-Ausdrücken vereinfachen:

Thread thread = new Thread(() -> System.out.println("Hello, World!"));
thread.start();

Die Logik dieses Codes ist dieselbe wie die des vorherigen Codes: Definieren Sie eine Klasse und implementieren Sie die Runnable-Schnittstelle. Erstellen Sie dann eine Instanz dieser Klasse und übergeben Sie sie an den Konstruktor der Thread-Klasse, um bei Bedarf Threads zu erstellen. Darunter stellt es einen Lambda-Ausdruck ​() -> {...}​dar und sein Funktionskörper ist ein Codeblock, der zur Ausgabe von „Hello, World!“ verwendet wird.

7. Verwendung von Lambda-Ausdrücken zur Implementierung von Komparatoren

In Java müssen wir häufig Daten sortieren. Normalerweise müssen wir eine Comparator-Schnittstelle implementieren, um die Sortierung zu definieren, und sie dann an die Sortiermethode übergeben. Der folgende Code definiert beispielsweise eine Klasse und eine Comparator-Implementierungsklasse und verwendet die Comparator-Implementierungsklasse zum Sortieren von Daten:

class Person {
    String name;
    int age;
    
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
}

class AgeComparator implements Comparator<Person> {
    public int compare(Person p1, Person p2) {
        return p1.age - p2.age;
    }
}

List<Person> persons = new ArrayList<>();
persons.add(new Person("Alice", 18));
persons.add(new Person("Bob", 20));
persons.add(new Person("Charlie", 25));
persons.add(new Person("David", 30));
persons.sort(new AgeComparator());

Wir können diesen Vorgang mithilfe von Lambda-Ausdrücken vereinfachen:

List<Person> persons = new ArrayList<>();
persons.add(new Person("Alice", 18));
persons.add(new Person("Bob", 20));
persons.add(new Person("Charlie", 25));
persons.add(new Person("David", 30));
persons.sort((p1, p2) -> p1.age - p2.age);

Die Logik dieses Codes ist dieselbe wie beim vorherigen Code: Es werden eine Klasse und eine Comparator-Implementierungsklasse definiert, und die Comparator-Implementierungsklasse wird zum Sortieren der Daten verwendet. Darunter stellt es einen Lambda-Ausdruck ​(p1, p2) -> {...}​dar , und sein Funktionskörper ist ein Codeblock, der zum Vergleichen der Alterseigenschaft zweier Personenobjekte verwendet wird.

8. Verwenden Sie Lambda-Ausdrücke, um die Konvertierung von Sammlungen zu realisieren

In Java können wir die Stream-API verwenden, um verschiedene Vorgänge für Sammlungen auszuführen. Eine häufige Operation besteht darin, eine Sammlung in eine andere Sammlung umzuwandeln. Der folgende Code definiert beispielsweise eine Klasse und eine List-Instanz und verwendet die Stream-API, um diese List-Instanz in eine andere List-Instanz zu konvertieren:

class Person {
    String name;
    int age;
    
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
}

List<Person> persons = new ArrayList<>();
persons.add(new Person("Alice", 18));
persons.add(new Person("Bob", 20));
persons.add(new Person("Charlie", 25));
persons.add(new Person("David", 30));

List<String> names = new ArrayList<>();
for (Person person : persons) {
    names.add(person.name);
}

Wir können diesen Vorgang mithilfe von Lambda-Ausdrücken vereinfachen:

List<Person> persons = new ArrayList<>();
persons.add(new Person("Alice", 18));
persons.add(new Person("Bob", 20));
persons.add(new Person("Charlie", 25));
persons.add(new Person("David", 30));

List<String> names = persons.stream().map(person -> person.name).collect(Collectors.toList());

Die Logik dieses Codes ist dieselbe wie die des vorherigen Codes: Es werden eine Klasse und eine List-Instanz definiert, und die Stream-API wird verwendet, um die List-Instanz in eine andere List-Instanz zu konvertieren. Darunter stellt es einen Lambda-Ausdruck ​person -> person.name​dar und sein Funktionskörper ist ein Codeblock, der zum Konvertieren des Person-Objekts in seine Namenseigenschaft verwendet wird. Die Methode​map​ wendet auf jedes Element in der Sammlung eine Funktion an und wandelt es in ein anderes Element um. ​collect​Die Funktion der Methode

9. Verwenden von Lambda-Ausdrücken zur Implementierung funktionaler Schnittstellen

In Java ist eine funktionale Schnittstelle eine Schnittstelle, die nur eine abstrakte Methode enthält. Lambda-Ausdrücke können problemlos funktionale Schnittstellen implementieren. Der folgende Code definiert beispielsweise eine funktionale Schnittstelle und eine Methode, die diese Schnittstelle verwendet:

@FunctionalInterface
interface MyFunction {
    void apply(String s);
}

void processString(String s, MyFunction f) {
    f.apply(s);
}

Wir können diese funktionale Schnittstelle mithilfe eines Lambda-Ausdrucks implementieren, der an ​processString​die Methode :

processString("Hello, World!", s -> System.out.println(s));

​Die Logik dieses Codes ist dieselbe wie die des vorherigen Codes: Eine funktionale Schnittstelle wird definiert und eine Methode, die diese Schnittstelle verwendet, wird definiert. Darunter stellt es einen Lambda-Ausdruck ​s -> System.out.println(s)​dar und sein Funktionskörper ist ein Codeblock, der zur Ausgabe einer Zeichenfolge verwendet wird. Wir übergeben diesen Lambda-Ausdruck an ​processString​die Methode , die die ​apply​Methode des Lambda-Ausdrucks aufruft und einen String-Parameter übergibt. Der Funktionskörper des Lambda-Ausdrucks gibt den Parameter an die Konsole aus.

Zusammenfassen

In diesem Artikel haben wir das Konzept und die Syntax von Lambda-Ausdrücken vorgestellt und die Anwendung von Lambda-Ausdrücken anhand praktischer Codebeispiele demonstriert.

Supongo que te gusta

Origin blog.csdn.net/bairo007/article/details/132338702
Recomendado
Clasificación