JAVA-C1
Funktionale Programmierung
@! Spungmarken in allen Pages testen!
Funktionale Programmierung
Function as Value
Pure Function
Higher-Order Functions
@FunctionalInterface Annotation
Methoden-Referenzen
Bedeutung von Stream API
Optional als neuer Typ
Zusammengefasst
Funktionales Interface
@FunctionalInterface
Lambda-Expressions
Simple / Komplex
Scope
Custom-Functional-Interfaces
Custom-Functional-Interfaces
Custom-Functional-Interfaces
Herkömmliches Interface
Funktionales Interface IRechnerDouble definieren und verwenden.
Generische funktionale Interfaces
@FunctionalInterface
Beispiele mit IRechnerGenericFlexible<Integer> r = ..
Beispiel: Lambda-Rechenoperationen mit Objekten
Beispiel: IRead T, IUpdate T, I Read T, IPrint T
Predefined Functional Interfaces
Overview
Function
BiFunction
Predicate
Supplier
Consumer
Diagramm aller Predefined Functional Interfaces
Diagramm Converter Interfaces
ToIntFunction/ToIntBiFunction
DoubleBinaryOperator (EXAMPLE)
@! Sprunmarken ergänzen/testen!
plugin-and-command-pattern-architecture
Beispiel/Collection
Overview
Lambda Expressions/Overview
Lambda-Expressions sind funktionale Ausdrücke für welche es inzwischen in vielen Skript- und Programmiersprachen eine Syntax mit Hilfe des sogenannten Arrow-Operators gibt.
Lambda-Expressions dienen mitunter dazu, eine Funktion oder auch eine Methode referenzieren zu können.
@FunctionalInterface
FunctionalInterface | @FunctionalInterface
Datentypen für Funktionale Interfaces.
Funktionale Interfaces dienen der Typisierung von Variablen werden Wert eine Referenz auf Methoden, Funktionen oder einen Lambda-Ausdruck beinhalten soll. Funktionale Interfaces sind deshalb vom Prinzip eigentlich Interfaces wie man die für andere Typen auch kennt, das aber mit der Besonderheit, dass diese für Methoden-Referenzen dienen, und ein solches Interface auch stets nur eine einzige Methode haben darf.
Um dokumentieren können, dass der Typ im Gegensatz zu späteren Implementierungsklassen
nur eine einzige Methode haben soll, wird die @FunctionalInterface Annotation
ergänzt.
/**
* Ein normales funktionales Interface
*/
@FunctionalInterface
interface IOperation {
int operate(int a, int b); // IOperation verdoppeln = (a)->a*a;
}
/**
* Eine generische Version eines funktionalen Interfaces
*/
@FunctionalInterface
interface IOperationGenerisch<T> {
T operate(T a, T b); // IOperationGenerisch<Integer> verdoppeln = (a)->a*a;
}
Merke: Viele Funktionale Interfaces sind Teil von Java, aber man kann diese auch selbst entwickeln.
Merke: Funktionale Interfaces können auch generische Typparameter bekommen.
Lambda Expression
FunctionalInterface | Lambda Expression
Syntax von Lambda-Expressions in Java
Die Syntax von Lambda-Expressions entspricht der Syntax in vielen anderen Sprachen.
Verwendet wird neben dem Funktionsoperator () zur Auszeichnung der Parameter des Lambda-Ausdrucks auch der Arrow-Operator oder Pfeil-Operator -> nach welchem der eigentliche Programmcode des Lambda-Ausdrucks oder der Körper der Expression in veschweiften Klammern folgt, sofern es sich nicht um einen Einzeiler handelt.
In einer typisierten Programmiersprache wie Java muss jeder Lambda-Ausdruck immer einen Typ haben. Dieser Typ wird entweder aus den Kontext eines Methodenparameters vorgegeben, über welchen das Lambda referenziert wird oder aber über den Typ einer Variable, in welcher der Ausdruck gespeichert werden soll.
Lambda-Ausdruck als "Expression-Lambda" Kurzform im Einzeiler
Wenn eine Lamda-Ausdruck nur aus einer einzigen Zeile mit den Return-Wert
entspricht, kann man geschweifte Klammern und auch das return
Statement weglassen.
IOperation add = (a, b) -> a + b;
IOperationGenerisch<Integer> verdoppeln = (a)->a*a;
Da die IOperation, siehe oben, nur eine Methode mit int-Parametern hat, brauchen im Lambda-Ausdruck keine Typen mehr angegeben zu werden.
Im Falle generischer funktionaler Interfaces muss zumindest der Typ für den Parameter angegeben werden, aber wiederum dürfen die Typen im eigentlichen Lambda-Ausdruck fehlen.
Der Type BiFunction ist ein sogenanntes Funktionales Interfaces
von Java selbst
und damit ein Interface-Typ, mit welchen Referenzen auf Funktionen gespeichet und genutzt
werden können.
// Deklaration
BiFunction <String,String,String> verketten = (gruss,name)->gruss+" "+name+"!";
// Verwendung durch Aufruf mit Parametern.
String begrüßung = verketten("Hallo","Manuel Mustermann");
System.out.println(begrüßung);
Lambda-Ausdruck mit Block-Syntax für mehr mehreren Zeilen
Wenn der Programmcode des Lambda-Ausdrucks mehrere Zeilen beinhaltet,
ist dieser Block in geschweiften Klammern { sowie
} einzuschließen
und dem return Ausdruck auch
der return Befehl voranzustellen.
Java bietet von sich aus bereits eine Reihe von funktionalen Interfaces
welche direkt verwendet werden können, darunter das
funktionale Interface Function
sowie die BiFunction.
Function add = (a, b) -> a + b;
Function subtract = (a, b) -> {
int result = a - b;
return result;
};
import java.util.function.BiFunction;
public class BiFunctionExample {
public static void main(String[] args) {
// Deklaration einer BiFunction, die zwei Strings verknüpft
BiFunction<String, String, String> verketten = (gruss, name) -> gruss + " " + name + "!";
// Verwendung durch Aufruf der apply-Methode mit Parametern
String begruessung = verketten.apply("Hallo", "Manuel Mustermann");
// Ausgabe
System.out.println(begruessung); // Ausgabe: Hallo Manuel Mustermann!
}
}
Die apply(..)Methode ist eine Methode
welche über das funktionale Interface BiFunction
vorgegeben wird.
Scope
Lambdas | Scope
Scope von Lambda-Expressions in Java
Der Gültigkeitsbereich von Lambda-Ausdrücken unterscheidet sich von herkömmlichen Methoden dahingehend, dass ein Lambda-Ausdruck den selben Sichtbarkeits- und Gültigkeitsbereich hat wie die Methode, in welcher der Lambda-Ausdruck defininert wurde. Dieses kann dazu führen, dass auf lokale Variablen außerhalb des Lambdas zugegriffen werden kann.
Der Gültigkeitsbereich von lokalen Variablen einer Methode erstreckt sich deshalb im Umkehrschluss auch auf den Programmcode aller Lambda-Expressions, welche in diese Methode definiert wurden.
Beispiel
Lambdas | Scope Example
Lambda-Ausdruck im Einzeiler
Ein Lambda-Ausdruck kann auch Variablen außerhalb seines eigenen Blocks verwenden, wenn diese in der umgebenden Methode deklariert wurden. In diesem Fall gelten auch diese Variablen für den Code des Lambda-Ausdrucks als lokale Variablen.
class LambdaExamples {
public static BiFunction<String,String,String> textLambda;
public static void main(String args) {
lambdaDefinieren();
}
public static void lambdaDefinition() {
// Wir definieren zwei lokale Variablen innerhalb dieser statischen Methode
// auf deren Werte der Lambda-Ausdruck in einem quasi-statischen Kontext
// weiterhin zugreifen kann.
String leerzeichen = " ";
String ausrufezeichen = "!";
// Definition eines Lambda-Ausdrucks.
verketten = (gruss,name) -> {
String aggregation =
gruss // aus Parameter des Lambda-Ausdrucks gem. ersten Typparameter
+leerzeichen // aus lokaler Variablen der umschließenden Methode
+name // aus Parameter gem. des zweiten Typparameters
+ausrufezeichen; // aus lokaler Variablen der umschließenden Methode
return aggregation;
}
LambdaExamples.textLambda = verketten; // Speichern in Classmember.
}
public static void lambdaUsage() {
// Verwendung
String begrüßung = LambdaExamples.textLambda("Hallo","Manuel Mustermann");
System.out.println(begrüßung);
}
}
Links
Quellen, Notes, Tags
Lambda-Expressions
UIO3 Es ist einfacher als Du denkst.
Stelle noch heute Deine Anfrage.
