Funktionale Programmierung Lambda – Functional Interfaces, Streams, map, filter, reduce
Dieser Beitrag ist eine Begriffserklärung zur funktionalen Programmierung – inklusive Prüfungsfragen und Tags.
In a Nutshell
Funktionale Programmierung fokussiert auf Berechnung über Funktionen statt Zustandsänderungen, Lambda-Ausdrücke sind Inline Funktionsliterale, in Java werden sie über Functional Interfaces, genau eine abstrakte Methode, an die Laufzeit gebunden.
Kompakte Fachbeschreibung
Ein Lambda-Ausdruck beschreibt anonymes Verhalten mit Parametern, Rumpf und optionalem Rückgabetyp, der Typ wird aus dem Zielkontext, Target Typ, hergeleitet, etwa einem Functional Interface wie Predicate, Function, Consumer, Supplier. Functional Interfaces ermöglichen Higher Order Functions, Funktionen werden als Werte übergeben, zurückgegeben, gespeichert. Zentrale Prinzipien sind Pure Functions, unveränderlicher Input führt zu determiniertem Output ohne Seiteneffekt, Referentielle Transparenz und Immutabilität reduzieren Kopplung und erleichtern Testing und Parallelisierung.
Prüfungsrelevante Stichpunkte
- Lambda Syntax kennen, Parameterliste, Pfeil, Rumpf, Target Typ durch Functional Interface
- Standardinterfaces, Function T,R, Predicate T, Consumer T, Supplier T, UnaryOperator T, BinaryOperator T
- Streams, map, filter, flatMap, reduce, collect, kurz erklären und typische Komplexität begründen
- IHK relevant, Unterschiede imperativ vs funktional, Seiteneffekte vermeiden, Vorteile für Testbarkeit und Parallelisierung
- Praxis, Methodenreferenzen, ClassName::staticMethod, instance::method, Constructor::new
- Sicherheitsaspekt, keine versteckten Seiteneffekte in Lambdas, Thread Sicherheit durch Immutabilität
- Wirtschaftlichkeit, weniger Boilerplate, klarer Datenfluss, bessere Wartbarkeit, potenziell geringere Fehlerquote
- Dokumentationspflicht, Vertrag der Funktion, Input Domäne, Seiteneffekte, Nebenläufigkeit, Komplexität
Kernkomponenten
- Lambda-Ausdruck Syntax, Parameter, Rumpf, Rückgabe
- Functional Interface mit genau einer abstrakten Methode, SAM
- Methodenreferenzen als kompakte Schreibweise
- Higher Order Functions, Funktionen als Parameter oder Rückgabewerte
- Pure Function und Seiteneffekte, Testbarkeit, Determinismus
- Immutabilität und Thread Sicherheit
- Stream Pipeline, Lazy Evaluation, Kurzschlussoperatoren
- Closure und effektiv final in Java
- Optionale und Fehlermuster, Optional, Try, Either Konzepte
- Parallel Streams, Daten Unabhängigkeit, Boxed vs. Primitive Streams
Praxisbeispiel
// Java, Daten filtern und transformieren mit Lambdas und Streams
List<String> names = List.of("Mila", "Tom", "Amir", "Mara")
List<Integer> lengths = names.stream()
.filter(n -> n.startsWith("M"))
.map(String::length)
.sorted()
.toList()
// Custom Functional Interface und Lambda
@FunctionalInterface
interface IntOp { int apply(int a, int b) }
IntOp add = (a, b) -> a + b
IntOp max = Math::max
int r1 = add.apply(3, 4) // 7
int r2 = max.apply(5, 9) // 9
Erklärung: Die Stream Pipeline zeigt map, filter, sorted, toList, die Lambdas sind pure und nebenwirkungsfrei.
Vorteile und Nachteile
Vorteile
- Weniger Boilerplate, klarer deklarativer Stil
- Bessere Testbarkeit durch Pure Functions
- Einfache Parallelisierung dank Immutabilität
- Hohe Wiederverwendbarkeit durch Kombinatoren
Nachteile
- Lernkurve bei Abstraktionen wie Higher Order Functions
- Debugging in Pipelines schwieriger
- Unbedachte Captures können Speicher binden
- In Java Limitierung durch effektiv final und Erasure
Typische Prüfungsfragen (mit Kurzantwort)
-
Lambda-Ausdruck in Java und Typbestimmung? Anonymes Funktionsliteral, der Typ ergibt sich aus dem Zielkontext, einem Functional Interface mit einer abstrakten Methode.
-
Vier zentrale Functional Interfaces aus java.util.function? Function T,R, Predicate T, Consumer T, Supplier T, zusätzlich Operatoren für T nach T.
-
Methode als Lambda vs. Methodenreferenz? Methodenreferenzen verweisen direkt auf bestehende Methoden, sind äquivalent zu einem Lambda, aber kürzer und lesbarer.
-
Effektiv final bei Closures? Lokale Variablen, die in Lambdas verwendet werden, dürfen nach der Zuweisung nicht mehr verändert werden, die JVM kann sie sicher capturen.
-
Referentielle Transparenz und warum wichtig? Ausdruck kann durch seinen Wert ersetzt werden ohne das Programmverhalten zu ändern, fördert Testbarkeit und reasoning.
-
Reduce in Stream Pipeline funktioniert? Kombiniert Elemente iterativ mit einem assoziativen Akkumulator und optional Identität, z.B. reduce(0, Integer::sum).
-
Risiken bei Parallel Streams? Nicht assoziative Akkumulatoren führen zu falschen Ergebnissen, seiteneffektbehaftete Lambdas sind unsafe.
-
Fehler funktional modellieren? Über Werte wie Optional für Abwesenheit, Try oder Either für Erfolg oder Fehler, statt globale Exceptions zu werfen.
-
Imperative Schleife vs. funktionale Pipeline? Imperativ, explizite Mutation und Kontrolle, funktional, deklarativer Datenfluss, Immutabilität, leichter testbar.
-
Functional Interfaces vs. echte Funktionstypen? Java nutzt SAM Typen als Ersatz, während Sprachen wie Kotlin, Scala, Haskell native Funktionstypen mit Typarität besitzen.
Wichtigste Quellen
- https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html
- https://docs.oracle.com/javase/8/docs/api/java/util/function/package-summary.html
- https://de.wikipedia.org/wiki/Funktionale_Programmierung