Funktionale Programmierung in Java: Fortgeschrittene Techniken und Stream API

Online Python-Trainer für Anfänger

Lernen Sie Python einfach ohne theoretische Überlastung. Lösen Sie praktische Aufgaben mit automatischer Überprüfung und schreiben Sie Code direkt im Browser.

Kurs starten

Funktionale Programmierung in Java: Fortgeschrittenes Niveau

\n\n

Funktionale Programmierung (FP) in Java ist nicht mehr nur ein modischer Trend – sie ist ein wesentlicher Bestandteil der modernen Sprache, beginnend mit Version 8. Für Entwickler, die die grundlegenden Lambdas und die Stream API beherrschen, beginnt eine Phase, in der ein Verständnis tiefergehender Konzepte erforderlich ist: Monaden, Funktionskomposition, faule Berechnungen und unveränderliche Datenstrukturen. Dieser Artikel widmet sich fortgeschrittenen Techniken der funktionalen Programmierung in Java, die helfen, saubereren, vorhersagbareren und nebenläufigkeitssicheren Code zu schreiben.

\n\n

1. Funktionskomposition und Currying

\n\n

In Java bieten die funktionalen Interfaces Function, Predicate und Consumer Standardmethoden für die Komposition: andThen() und compose(). Dies ermöglicht den Aufbau von Transformationsketten ohne die Erstellung von Zwischenvariablen.

\n\n

Beispiel für Komposition:

\n
import java.util.function.Function;\n\npublic class FunctionComposition {\n    public static void main(String[] args) {\n        Function<String, String> trim = String::trim;\n        Function<String, String> toUpper = String::toUpperCase;\n        Function<String, String> addExclamation = s -> s + "!";\n\n        // Komposition: trim -> toUpper -> addExclamation\n        Function<String, String> process = trim.andThen(toUpper).andThen(addExclamation);\n\n        String result = process.apply("  hello world  ");\n        System.out.println(result); // HELLO WORLD!\n    }\n}
\n\n

Currying ist die Umwandlung einer Funktion mit mehreren Argumenten in eine Folge von Funktionen mit einem Argument. In Java kann dies mit Hilfe von verschachtelten Lambdas emuliert werden:

\n\n
import java.util.function.Function;\n\npublic class CurryingExample {\n    // Normale Funktion\n    static int add(int a, int b) { return a + b; }\n\n    // Curry-Version\n    static Function<Integer, Function<Integer, Integer>> curriedAdd = a -> b -> a + b;\n\n    public static void main(String[] args) {\n        // Partielle Anwendung\n        Function<Integer, Integer> add5 = curriedAdd.apply(5);\n        System.out.println(add5.apply(3)); // 8\n        System.out.println(add5.apply(10)); // 15\n    }\n}
\n\n

Currying ist nützlich, um spezialisierte Funktionen auf der Grundlage allgemeiner Vorlagen zu erstellen, insbesondere bei der Arbeit mit Konfigurationen.

\n\n

2. Fortgeschrittene Arbeit mit der Stream API

\n\n

Die Stream API in Java ist nicht nur ein Ersatz für Schleifen. Das Verständnis ihrer fortgeschrittenen Möglichkeiten ermöglicht es, die Leistung und Lesbarkeit des Codes erheblich zu verbessern.

\n\n

2.1. Parallele Streams und Spliteratoren

\n

Parallele Streams verwenden ForkJoinPool. Ihre Effizienz hängt jedoch von der Datenmenge und der Art der Operationen ab. Für eine benutzerdefinierte Steuerung der Parallelisierung kann Spliterator verwendet werden.

\n\n
import java.util.Spliterator;\nimport java.util.stream.Stream;\nimport java.util.stream.StreamSupport;\n\npublic class CustomSpliterator {\n    public static void main(String[] args) {\n        // Erstellen eines Streams aus einem Iterator mit benutzerdefiniertem Spliterator\n        Spliterator<Integer> spliterator = new Spliterator<>() {\n            int current = 0;\n            @Override\n            public boolean tryAdvance(java.util.function.Consumer<? super Integer> action) {\n                if (current < 100) {\n                    action.accept(current++);\n                    return true;\n                }\n                return false;\n            }\n            @Override\n            public Spliterator<Integer> trySplit() {\n                // Einfachste Aufteilung\n                int mid = current + 50;\n                if (mid >= 100) return null;\n                Spliterator<Integer> prefix = new RangeSpliterator(curre                

Blogs

Buchempfehlungen