53
Java 8 mit Lambdas das hohe Lied des Functional Programming singen IPS-Expertenkreis Dr. Hubert Austermeier ORDIX AG 03.07.2014 [email protected] www.ordix.de

Java 8, mit Lambdas das hohe Lied des Functional Programming singen

Embed Size (px)

DESCRIPTION

Vortrag auf dem Expertenkreis Java am 3.7.2014

Citation preview

Page 1: Java 8, mit Lambdas das hohe Lied des Functional Programming singen

Java 8 mit Lambdas das hohe Lied des

Functional Programming singen

IPS-Expertenkreis

Dr. Hubert Austermeier

ORDIX AG

03.07.2014

[email protected]

www.ordix.de

Page 2: Java 8, mit Lambdas das hohe Lied des Functional Programming singen

� Motivation, Einführung

� Definitionen zu Lambda Expressionss

� Voraussetzungen: funktionale Schnittstellen

� Noch kürzer: Referenzen auf Methoden/Konstruktoren

� Streams: profitieren stark von Lambda Expressions

Agenda

� Streams: profitieren stark von Lambda Expressions

� Streams im Einsatz

� Lösungen mittels Lambda Expressions

Java 8 - Lambda Expressions, IPS Expertenkreis, 03.07.2014 1

Page 3: Java 8, mit Lambdas das hohe Lied des Functional Programming singen

� Es finden 3 String-Additionen und 2 toString() Konversionen statt

– auch dann, falls der Log Level auf Warning steht!

Probleme! Welche Probleme?

logger.info("x: " + x + ", y: " + y);

� Keine Chance, diesen Code auf einem 8-Kern Rechner parallel laufen zu lassen

Java 8 - Lambda Expressions, IPS Expertenkreis, 03.07.2014 2

for (BusinessObj b : listOfBO)

b.doComplexWork();

Page 4: Java 8, mit Lambdas das hohe Lied des Functional Programming singen

Probleme…

saveButton.addActionListener(new ActionListener() {

@Override

public void actionPerformed(ActionEvent e) {

saveActions(e.getActionCommand());

}

});

� Hässlich, einfach nur hässlich…

übrigens nicht nur für Entwickler, auch für die JVM!

Java 8 - Lambda Expressions, IPS Expertenkreis, 03.07.2014 3

Page 5: Java 8, mit Lambdas das hohe Lied des Functional Programming singen

� Die zuvor gezeigten "Probleme" haben etwas gemeinsam:

mögliche Lösungen haben mit Funktionen zu tun;

Funktionen, die für eine Parameterübergabe taugen

� Das führt zu Lambda Expressions, kurz Lambdas, welche die

bedeutendste Neuerung in Java 8 (seit März draußen) darstellen

Was kann helfen?

bedeutendste Neuerung in Java 8 (seit März draußen) darstellen

� Die konkreten Lösungen schauen wir uns später an…

Java 8 - Lambda Expressions, IPS Expertenkreis, 03.07.2014 4

Page 6: Java 8, mit Lambdas das hohe Lied des Functional Programming singen

� Lambdas sind seit langem auf der Agenda des Java-Fortschritts

� benannt nach dem griechischem λ – und nach dem Lambda Kalkül

� entwickelt in den 1930‘er Jahren zur Untersuchung von Funktionen

und deren Berechenbarkeit (A. Church, et al.)

Lambdas Grundsätzliches

� sollen das Prinzip des "Functional Programming" in Java befördern

� bekannte, funktionale Programmiersprachen sind Lisp, Scheme, Haskell, …

� Lambdas sollen u.a. die sperrigen, unleserlichen Anonymen Klassen

ablösen

� werden zunehmend wichtig für das Thema "Multithreading“

Java 8 - Lambda Expressions, IPS Expertenkreis, 03.07.2014 5

Page 7: Java 8, mit Lambdas das hohe Lied des Functional Programming singen

� Der Begriff Closure ist sehr verbreitet in der IT und bedeutet vereinfacht:

� Code, der herumgereicht werden kann, z.B. an eine Methode, die

diesen Code verzögert ausführen kann � deferred execution

� Closure heißt es vielen Programmiersprachen (Scheme, Lisp, Scala, …),

Closure dort, Lambda hier

� Closure heißt es vielen Programmiersprachen (Scheme, Lisp, Scala, …),

� für Java wurde die Bezeichnung Lambda gewählt

� Man findet auch den Begriff "Code as Data"

� soll heißen, dass Code herumgereicht wird genauso wie Daten

Java 8 - Lambda Expressions, IPS Expertenkreis, 03.07.2014 6

Page 8: Java 8, mit Lambdas das hohe Lied des Functional Programming singen

In einem Blog Beitrag von James Gosling (Java Protagonist) findet

sich etwas zur Historie des Closure Themas in Java

(http://www.javaworld.com/#resources)

etwas Historie: Closures vs inner classes

Closures were left out of Java initially more because of

time pressures than anything else.

Java 8 - Lambda Expressions, IPS Expertenkreis, 03.07.2014 7

time pressures than anything else.

In the early days of Java the lack of closures was

pretty painful, and so inner classes were born:

an uncomfortable compromise that attempted to avoid

a number of hard issues. But as is normal in so

many design issues, the simplifications didn't really solve

any problems, they just moved them.

Page 9: Java 8, mit Lambdas das hohe Lied des Functional Programming singen

� Beispiel in Java 8:

� (a, b) -> a + b

� symbolisiert die Funktion: Berechne die Summe von zwei Parametern

� (der Typ von a und b ergibt sich aus dem Kontext, dazu später mehr)

Wie sieht eine Lambda Expression denn nun aus?

dazu später mehr)

Java 8 - Lambda Expressions, IPS Expertenkreis, 03.07.2014 8

Page 10: Java 8, mit Lambdas das hohe Lied des Functional Programming singen

� Motivation, Einführung

� Definitionen zu Lambda Expressionss

� Voraussetzungen: funktionale Schnittstellen

� Noch kürzer: Referenzen auf Methoden/Konstruktoren

� Streams: profitieren stark von Lambda Expressions

Agenda

� Streams: profitieren stark von Lambda Expressions

� Streams im Einsatz

� Lösungen mittels Lambda Expressions

Java 8 - Lambda Expressions, IPS Expertenkreis, 03.07.2014 9

Page 11: Java 8, mit Lambdas das hohe Lied des Functional Programming singen

� syntaktisch besteht einer Lambda Expression aus:

� einer Liste von Parametern, durch Komma getrennt

� einem Methodenrumpf

� Zwischen Parameterliste und Methodenrumpf steht das "->" Symbol:

Syntax von Lambda Expressions

� oder einfacher:

Java 8 - Lambda Expressions, IPS Expertenkreis, 03.07.2014 10

String[] names = {"Thomas", "Sebastian", "Uli", "Tobias", "Andreas"};

names.forEach((String element) -> { System.out.println(element); });

names.forEach(element -> System.out.println(element));

Page 12: Java 8, mit Lambdas das hohe Lied des Functional Programming singen

� der Datentyp der Parameter wird aus dem Kontext abgeleitet

� Zugriff auf Variablen des "umliegenden Scopes" ist möglich,

falls sie effektiv unveränderlich sind

� der Modifier final ist mit Java 8 nicht mehr obligatorisch

weitere Definitionen

� Gültigkeitsbereiche:

� this bezieht sich auf die Instanz der Klasse,

in welcher Lambda Expression steht

� super verweist auf die Oberklasse der Klasse,

in welcher Lambda Expression steht

Java 8 - Lambda Expressions, IPS Expertenkreis, 03.07.2014 11

Page 13: Java 8, mit Lambdas das hohe Lied des Functional Programming singen

Anonyme Klasse vs. Lambda Expression

String[] names = {"Thomas", "Sebastian", "Uli", "Tobias", "Andreas"};

// Anonyme Klasse

Arrays.sort(names, new Comparator<String>() {

@Override

public int compare(String name1, String name2) {

return name1.compareTo(name2);

}

Java 8 - Lambda Expressions, IPS Expertenkreis, 03.07.2014 12

}

});

// Lambda Expression

Arrays.sort(names, (name1, name2) -> name1.compareTo(name2));

Page 14: Java 8, mit Lambdas das hohe Lied des Functional Programming singen

� Lambda Expressions können auch mehrere Anweisungen enthalten

� der Anweisungsblock wird dann in geschweifte Klammern gesetzt

Mehrzeilige Lambda Expressions

Collections.sort(liste, (person1, person2) -> {

int c = person1.getVorname().compareTo(person2.getVorname());

if (c == 0)

Java 8 - Lambda Expressions, IPS Expertenkreis, 03.07.2014 13

if (c == 0)

c = person1.getNachname().compareTo(person2.getNachname());

return c;

});

Page 15: Java 8, mit Lambdas das hohe Lied des Functional Programming singen

� Lambda Expressions können genutzt werden bei:

� Variablen-Initialisierung oder -zuweisung

� Argumentposition

� Ergebnisrückgabe mit return

� Rumpf eines größeren Lambda-Ausdrucks

� Operand eines bedingten Ausdrucks (dreistelliger Operator ?:)

Lambda Expression dürfen wo stehen?

� Operand eines bedingten Ausdrucks (dreistelliger Operator ?:)

� generell überall, wo die Instanz eines Functional Interface stehen kann

� im Gegensatz zu anonymen Klassen werden keine zusätzlichen

Bytecode-Dateien generiert!

Java 8 - Lambda Expressions, IPS Expertenkreis, 03.07.2014 14

Page 16: Java 8, mit Lambdas das hohe Lied des Functional Programming singen

� Motivation, Einführung

� Definitionen zu Lambda Expressionss

� Voraussetzungen: funktionale Schnittstellen

� Noch kürzer: Referenzen auf Methoden/Konstruktoren

� Streams: profitieren stark von Lambda Expressions

Agenda

� Streams: profitieren stark von Lambda Expressions

� Streams im Einsatz

� Lösungen mittels Lambda Expressions

Java 8 - Lambda Expressions, IPS Expertenkreis, 03.07.2014 15

Page 17: Java 8, mit Lambdas das hohe Lied des Functional Programming singen

� sind Interfaces mit einer einzigen, abstrakten Methode

� sog. SAM Interface (Single Abstract Method)

� @FunctionalInterface markiert ein Functional Interface

� Compiler kann damit prüfen, ob es valide ist

Functional Interfaces

� sind Voraussetzung für Lambda Expressions, welche eine

kompakte Schreibweise bieten

� Interfaces in Java 8 können default-Methoden implementieren!

� (wichtig für Rückwärtskompabilität)

Java 8 - Lambda Expressions, IPS Expertenkreis, 03.07.2014 16

Page 18: Java 8, mit Lambdas das hohe Lied des Functional Programming singen

Functional Interfaces…

@FunctionalInterface

public interface MyFunctionalInterface {

void takeTime(LocalDateTime time);

default String timeFormatter(LocalDateTime time) {

return time.format(DateTimeFormatter.ISO_DATE);

Java 8 - Lambda Expressions, IPS Expertenkreis, 03.07.2014 17

return time.format(DateTimeFormatter.ISO_DATE);

}

}

Page 19: Java 8, mit Lambdas das hohe Lied des Functional Programming singen

� Motivation, Einführung

� Definitionen zu Lambda Expressionss

� Voraussetzungen: funktionale Schnittstellen

� Noch kürzer: Referenzen auf Methoden/Konstruktoren

� Streams: profitieren stark von Lambda Expressions

Agenda

� Streams: profitieren stark von Lambda Expressions

� Streams im Einsatz

� Lösungen mittels Lambda Expressions

Java 8 - Lambda Expressions, IPS Expertenkreis, 03.07.2014 18

Page 20: Java 8, mit Lambdas das hohe Lied des Functional Programming singen

� Lambda Expression führen oft nur eine einzige Methode aus

� Methoden Referenz bieten eine weitere, verkürzte Schreibweise

� die Methode wird über Typ::Namen referenziert

� neben dem Datentyp der Parameter, muss der Compiler auch

die Anzahl der Parameter aus dem Kontext ableiten

Methoden Referenzen

die Anzahl der Parameter aus dem Kontext ableiten

� die Methode wird nicht aufgerufen, sondern referenziert!

� Beispiel:

Java 8 - Lambda Expressions, IPS Expertenkreis, 03.07.2014 19

Integer[] numbers = {120 ,5, 90, 3, 1, 9, 14, 22, 2};

Arrays.stream(numbers).forEach(e -> System.out.println(e));

// geht einfacher mit Methoden Referenz

Arrays.stream(numbers).forEach(System.out::println);

Page 21: Java 8, mit Lambdas das hohe Lied des Functional Programming singen

� syntaktisch besteht eine Methoden Referenz aus:

� einem Receiver (Empfänger)

� Name der statischen Methode oder Instanzmethode

� durch “::“ verbunden

Syntax Methoden Referenzen

Java 8 - Lambda Expressions, IPS Expertenkreis, 03.07.2014 20

Syntax Beschreibung

Klasse::new Referenz auf einen Konstruktor

Klasse::statischeMethode Referenz auf eine statische Methode

Klasse::instanzMethodeReferenz auf eine Instanzmethode eines

beliebigen Objekts

Objekt::instanzMethodeReferenz auf eine Instanzmethode eines

bestimmten Objekts

Page 22: Java 8, mit Lambdas das hohe Lied des Functional Programming singen

Beispiele

// Methoden Referenz – statische Methode

Integer[] numbers = {120 ,5, 90, 3, 1, 9, 14, 22, 2};

Arrays.sort(numbers, Integer::compare);

//– nicht statische Methode

Java 8 - Lambda Expressions, IPS Expertenkreis, 03.07.2014 21

//– nicht statische Methode

String[] letters = {"V", "S", "C", "T", "A", "R", "H"};

Arrays.sort(letters, String::compareTo);

// - mittels eines bestimmten Objektes - bound

ComparisonProvider comparisonProvider = new ComparisonProvider();

personListe.sort(comparisonProvider::compareByName);

Page 23: Java 8, mit Lambdas das hohe Lied des Functional Programming singen

Beispiel: Klasse::new

// Konstruktor Referenz

String filesuffix = ".txt";

List<String> dataList = Arrays.asList("readme","releasenotes");

dataList.stream()

.map(StringBuilder::new)

.map(s->s.append(filesuffix));

Java 8 - Lambda Expressions, IPS Expertenkreis, 03.07.2014 22

Page 24: Java 8, mit Lambdas das hohe Lied des Functional Programming singen

� Motivation, Einführung

� Definitionen zu Lambda Expressionss

� Voraussetzungen: funktionale Schnittstellen

� Noch kürzer: Referenzen auf Methoden/Konstruktoren

� Streams: profitieren stark von Lambda Expressions

Agenda

� Streams: profitieren stark von Lambda Expressions

� Streams im Einsatz

� Lösungen mittels Lambda Expressions

Java 8 - Lambda Expressions, IPS Expertenkreis, 03.07.2014 23

Page 25: Java 8, mit Lambdas das hohe Lied des Functional Programming singen

� neue, mächtige API in Java 8, um effizienter Collections einzusetzen

� basieren stark auf Lambdas und Functional Interfaces

� ein Stream speichert keine Daten

� der Speicher besteht aus Collections, Arrays,…

Streams Grundsätzliches

� auf Streams finden Operationen (Methodenaufrufe) statt

� es wird z.B. nicht iteriert über einen Stream

� Stream Operationen ändern nicht ihre Quelle (z. B. eine List<…>)

� sie geben neue Streams zurück bzw. erzeugen Ergebnisse

Java 8 - Lambda Expressions, IPS Expertenkreis, 03.07.2014 24

Page 26: Java 8, mit Lambdas das hohe Lied des Functional Programming singen

� bislang mussten Entwickler vieles selbst programmieren:

Bspl.: "Iteration über ein Array und Elemente konkatenieren"

Stream API Motivation

String[] strArr = new String[]{"Hallo", ", ", "Welt"};

StringBuilder satz = new StringBuilder("");

for (String wort: strArr) {

� Nicht weiter schlimm, aber solcher Code ist z.B. schwer parallelisierbar!

Java 8 - Lambda Expressions, IPS Expertenkreis, 03.07.2014 25

for (String wort: strArr) {

satz.append(wort);

}

Page 27: Java 8, mit Lambdas das hohe Lied des Functional Programming singen

� in der Stream API stecken viele implizite Algorithmen; zum Iterieren gibt es beispielsweise die Methode: forEach

Iteration: forEach

String[] strArr = new String[]{"Hallo", ", ", "Welt"};

StringBuilder satz = new StringBuilder("");

Arrays.stream(strArr).forEach(satz::append);Arrays.stream(strArr).forEach(satz::append);

Java 8 - Lambda Expressions, IPS Expertenkreis, 03.07.2014 26

Page 28: Java 8, mit Lambdas das hohe Lied des Functional Programming singen

� Stream-Operationen lassen sich in 3 Kategorien unterteilen:

� Stream-Generierung (creation operation)

� Stream-Transformation (intermediate operation)

� werden 0..n mal angewendet

Stream Management

� werden 0..n mal angewendet

� liefern ihrerseits jeweils Streams zurück

� Abschlussberechnung (terminal operation)

� Sie werden auch in dieser Reihenfolge angewendet

Java 8 - Lambda Expressions, IPS Expertenkreis, 03.07.2014 27

Page 29: Java 8, mit Lambdas das hohe Lied des Functional Programming singen

� Motivation, Einführung

� Definitionen zu Lambda Expressionss

� Voraussetzungen: funktionale Schnittstellen

� Noch kürzer: Referenzen auf Methoden/Konstruktoren

� Streams: profitieren stark von Lambda Expressions

Agenda

� Streams: profitieren stark von Lambda Expressions

� Streams im Einsatz

� Lösungen mittels Lambda Expressions

Java 8 - Lambda Expressions, IPS Expertenkreis, 03.07.2014 28

Page 30: Java 8, mit Lambdas das hohe Lied des Functional Programming singen

� einen Stream zu einer Collection (List, Set, Map,…) bekommt man

über die Methode stream()

� Stream<String> s = stringSet.stream();

� ein Array ist auf 2 Arten umwandelbar zu einem Stream :

� Stream.of(anArray) liefert Stream für das gesamte Array

� Arrays.stream(anArray, von, bis) liefert Stream für einen

Stream-Generierung (I/II)

� Arrays.stream(anArray, von, bis) liefert Stream für einen

Abschnitt des Arrayes

� Stream.empty() liefert einen leeren Stream

� (kann nötig sein, falls leeres Ergebnis zurück zu geben ist)

Java 8 - Lambda Expressions, IPS Expertenkreis, 03.07.2014 29

Page 31: Java 8, mit Lambdas das hohe Lied des Functional Programming singen

� Stream.generate(Math::random) liefert Stream von Zufallszahlen

� weitere Java 8 API-Klassen liefern Streams als Resultat

� um Zeilen einer Datei auszulesen:Stream<String> lines = Files.lines(pFile);

Stream-Generierung (II/II)

Stream<String> lines = Files.lines(pFile);

� um eine Suche durchzuführen und die passenden "Matches" zu erhalten:Stream<String> words

= Pattern.compile(regExp).splitAsStream(contents);

Java 8 - Lambda Expressions, IPS Expertenkreis, 03.07.2014 30

Page 32: Java 8, mit Lambdas das hohe Lied des Functional Programming singen

� eine Stream-Transformation liest Daten aus einem Stream und

packt modifizierte Daten in einen anderen Stream

� Stream Transfomationen erfolgen häufig "lazy", d.h. erst wenn die

transformierten Daten benötigt werden, findet die Transformation statt

Stream-Transformation

� die filter() Operation modifiziert einen Ursprungsdatenstrom,

in dem nur Elemente durchkommen, die ein gewisses Kriterium erfüllen

Java 8 - Lambda Expressions, IPS Expertenkreis, 03.07.2014 31

Page 33: Java 8, mit Lambdas das hohe Lied des Functional Programming singen

� Suche nach oder Filtern von Elementen erforderte bislang

ein "aktives Suchen",

� z.B. mittels einer Suchschleife wie "zählen aller Strings mit Länge > 2"

Suchen in Listen

String[] strArr = new String[]{"Hallo", ", ", "Welt"}; int count = 0;

for (String s : strArr) if (s.length > 2) count++;

� Streams bieten dafür die Methode filter

Java 8 - Lambda Expressions, IPS Expertenkreis, 03.07.2014 32

Stream<String> strStream = Arrays.stream(strArr); int count = 0;

count = strSet.stream().filter(s -> s.length > 2).count();

Page 34: Java 8, mit Lambdas das hohe Lied des Functional Programming singen

� um die einzelnen Elemente eines Streams zu transformieren,rückt die Methode map() ins Blickfeld

� wird aufgerufen mit eine Lambda Expression (oder Methoden Referenz)

� diese bestimmt, wie der Typ des Transformationsergebnisses ist

Elemente umformen: map

� diese bestimmt, wie der Typ des Transformationsergebnisses ist

� map() erzeugt einen neuen Stream von Elementen

� des gleichen Typs, falls lambda: Function(T, T) ist

� vom Typ U, falls lambda: Function(T, U)

Java 8 - Lambda Expressions, IPS Expertenkreis, 03.07.2014 33

Page 35: Java 8, mit Lambdas das hohe Lied des Functional Programming singen

� Aufgabenstellung: eine Liste von Wörtern umformen, so dass eine

Sequenz resultiert mit allen Wörtern in Kleinbuchstaben

� Es greift der Mechanismus von map(): jedes Element wird einer

Transformation unterzogen und in einen neuen Stream gepackt

Beispiel: map

� oder mittels Methoden Referenz

Java 8 - Lambda Expressions, IPS Expertenkreis, 03.07.2014

List<String> wordList = ...;

Stream<String> words = wordList.stream();

Stream<String> lowercaseWords = words.map(s -> s.toLowerCase());

34

Stream<String> lowercaseWords = words.map(String::toLowerCase);

Page 36: Java 8, mit Lambdas das hohe Lied des Functional Programming singen

� Ausgangslage: Elemente eines Streams sind so zu transformieren, dass pro Element eine Container-Struktur entsteht (z.B. eine List<T>)

� Wunsch: es soll keine Ineinanderschachtelung stattfinden, wie z.B.Stream<List<T>>, sondern eine "flache" Struktur entstehen Stream<T>

Umformung Kaskadierung: flatMap

� Lösung: die Methode flatMap() liefert genau das

Java 8 - Lambda Expressions, IPS Expertenkreis, 03.07.2014 35

Page 37: Java 8, mit Lambdas das hohe Lied des Functional Programming singen

� die folgende Methode transformiert jeden String in einen

Stream<Character>:

BeispielS: flatMap

public static Stream<Character> characterStream(String s) {

List<Character> result = new ArrayList<>();

for (char c : s.toCharArray()) result.add(c);

return result.stream();

}

� Ergebnis von characterStream("boot") ist der Stream ['b', 'o', ‘o', 't']

� ein simples map() liefert eine verschachtelte Struktur

� flatMap hingegen löst die innere Struktur und liefert einen "flachen" Stream

Java 8 - Lambda Expressions, IPS Expertenkreis, 03.07.2014 36

Stream<Stream<Character>> result = words.map(w -> characterStream(w));

}

Stream<Character> letters = words.flatMap(w -> characterStream(w));

Page 38: Java 8, mit Lambdas das hohe Lied des Functional Programming singen

� Methoden, die eine endgültige Struktur oder einen Wert zurückgeben

� sorgen dafür, dass alle Berechnungen, Transformationen,

Filterungen, etc. tatsächlich stattfinden

� basieren hauptsächlich auf reduce() und collect()

Abschlussberechnung (terminal operation)

� basieren hauptsächlich auf reduce() und collect()

Java 8 - Lambda Expressions, IPS Expertenkreis, 03.07.2014 37

Page 39: Java 8, mit Lambdas das hohe Lied des Functional Programming singen

� um sukzessive, Element für Element zu rechnen und am

Ende ein Ergebnis zu liefern, eignet sich die Methode:reduce()

� es wird jeweils unter Hinzunahme eines weiteren Elementes

ein neues Zwischenergebnis gebildet

Einzelergebnisse aus Streams: reduce

ein neues Zwischenergebnis gebildet

� reduce() hat bis zu 3 Argumente:

� initialValue: Identitätswert; Operation mit diesem Wert liefert

identischen Wert, (0 bei Integer Addition)

� accumulator: "addiert" ein Element zu einem (Zwischen)ergebnis

� combiner: fasst zwei Zwischenergebnisse zu einem zusammen

Java 8 - Lambda Expressions, IPS Expertenkreis, 03.07.2014 38

Page 40: Java 8, mit Lambdas das hohe Lied des Functional Programming singen

� einfaches Beispiel: "Berechne die Summe von n Zahlen"

Beispiele: reduce

Stream<Integer> values = ...;

// mit 1 Argument

Optional<Integer> sum = values.reduce((x, y) -> x + y)

// oder mit 2 Argumenten; Optional ist nicht mehr nötig!

Integer sum = values.reduce(0, (x, y) -> x + y)

� bei einfachen Operationen ist wieder Methoden Referenz nutzbar

Java 8 - Lambda Expressions, IPS Expertenkreis, 03.07.2014 39

Integer sum = values.reduce(0, (x, y) -> x + y)

Stream<Integer> values = ...;

// Methoden-Referenz

Integer sum = values.reduce(0, Integer::sum)

Page 41: Java 8, mit Lambdas das hohe Lied des Functional Programming singen

� anderes Beispiel: "Bilde die Summe der Längen aller Strings";

� hier braucht man ein drittes Argument,

denn Teilergebnisse sind speziell zusammenzufassen

reduce mit combiner

int result = words.reduce(0,

(total, word) -> total + word.length(), // accumulator

(total1, total2) -> total1 + total2); // combiner

Java 8 - Lambda Expressions, IPS Expertenkreis, 03.07.2014 40

(total1, total2) -> total1 + total2); // combiner

Page 42: Java 8, mit Lambdas das hohe Lied des Functional Programming singen

� wenn als Ergebnis eine komplexere Struktur erwartert wird, wie z.B. ein HashSet, kann die Methode collect() genutzt werden

� es wird jeweils unter Hinzunahme eines weiteren Elementes

ein bestehendes Zwischenergebnis erweitert!

Strukturergebnisse aus Streams: collect

� collect() hat ebenfalls bis zu 3 Argumente:

� supplier: Initialisierungsfunktion; liefert eine leere Struktur

� accumulator: fügt ein Element einem (Zwischen)ergebnis hinzu

� combiner: fügt ein Zwischenergebnis mit einem zweiten zusammen

Java 8 - Lambda Expressions, IPS Expertenkreis, 03.07.2014 41

Page 43: Java 8, mit Lambdas das hohe Lied des Functional Programming singen

� Beispiel: "Bilde aus dem Stream von Strings eine HashSet-Struktur"

Beispiele: collect

HashSet<String> result =

words.collect(HashSet::new, HashSet::add, HashSet::addAll);

// ^ ^ ^

// supplier accumulator combiner

� In der Praxis nutzt man Factory-Methoden aus der Collectors-Klasse

Java 8 - Lambda Expressions, IPS Expertenkreis, 03.07.2014 42

// für Standard Collections gibt es vorgefertigte Methoden

Set<String> hSResult = words.collect(Collectors.toSet());

Page 44: Java 8, mit Lambdas das hohe Lied des Functional Programming singen

� Collectors-Klasse hat Angebote für alle gängigen Collections

collect...

List<String> lResult=

words.collect(Collectors.toList());

// oder etwas spezieller, nicht einfach Set, sondern TreeSet

TreeSet<String> tSResult =

words.collect(Collectors.toCollection(TreeSet::new));

� Beispiel: String-Zusammenfassung:

� "Bilde aus dem Stream von Strings einen Gesamtstring“

Java 8 - Lambda Expressions, IPS Expertenkreis, 03.07.2014 43

words.collect(Collectors.toCollection(TreeSet::new));

String result1 = words.collect(Collectors.joining());

// mit Trennzeichen zwischen Einzelstrings

String result2 = words.collect(Collectors.joining(", "));

Page 45: Java 8, mit Lambdas das hohe Lied des Functional Programming singen

� Es soll eine Liste von Personen in eine Map transformiert werden,

so dass später für eine ID ein Name gefunden werden kann

� (Annahme1: es gibt eine Person Klasse mit passenden Attributen)

� (Annahme2: es gibt eine people Variable vom Typ Stream<Person>)

Elemente in eine Map packen mittels collect

// Collectors.toMap() hat zwei Argumente

// 1: wie komme ich an den key

Java 8 - Lambda Expressions, IPS Expertenkreis, 03.07.2014 44

// 1: wie komme ich an den key

// 2: was ist der value

Map<Integer, String> idToName = people.collect(

Collectors.toMap(Person::getId, Person::getName));

// value soll das Objekt sein

Map<Integer, Person> idToPerson = people.collect(

Collectors.toMap(Person::getId, Function.identity());

Page 46: Java 8, mit Lambdas das hohe Lied des Functional Programming singen

� falls ein key mehr als einmal auftaucht, gibt es eine IllegalStateException

� ein drittes Argument kann Kollisionsbehandlung übernehmen

� Beispiel:

� „Konstruktion einer Map für die Sprachen alle verfügbaren Locales.

Als key fungiert der Namen im default Locale ("German"),

welcher als value den lokalisierten Namen hat ("Deutsch").“

Kollisionen behandeln

welcher als value den lokalisierten Namen hat ("Deutsch").“

Java 8 - Lambda Expressions, IPS Expertenkreis, 03.07.2014 45

Stream<Locale> locales = Stream.of(Locale.getAvailableLocales());

Map<String, String> languageNames = locales.collect(

Collectors.toMap(

l -> l.getDisplayLanguage(),

l -> l.getDisplayLanguage(l),

(existingValue, newValue) -> existingValue));

Locales: ar_AE, ar_JO, ar_SY, hr_HR, fr_BE, es_PA, ...

Page 47: Java 8, mit Lambdas das hohe Lied des Functional Programming singen

� Eine Liste von Elementen nach bestimmten Kriterien zu gruppieren,

ist eine häufig vorkommende Aufgabenstellung

� daher gibt es dafür die spezielle Methode groupingBy

� Beispiel: "Gruppiere alle Sprachen eines Landes“

Gruppierung durchführen: groupingBy

Java 8 - Lambda Expressions, IPS Expertenkreis, 03.07.2014 46

// groupingBy benötigt eine classifier function;

// hier: Locale::getCountry

Map<String, List<Locale>> countryToLocales =

locales.collect(Collectors.groupingBy(Locale::getCountry));

// Sprachen für die Schweiz:

List<Locale> swissLocales = countryToLocales.get("CH");

// Yields locales [it_CH, de_CH, fr_CH]

Page 48: Java 8, mit Lambdas das hohe Lied des Functional Programming singen

� Motivation, Einführung

� Definitionen zu Lambda Expressionss

� Voraussetzungen: funktionale Schnittstellen

� Noch kürzer: Referenzen auf Methoden/Konstruktoren

� Streams: profitieren stark von Lambda Expressions

Agenda

� Streams: profitieren stark von Lambda Expressions

� Streams im Einsatz

� Lösungen mittels Lambda Expressions

Java 8 - Lambda Expressions, IPS Expertenkreis, 03.07.2014 47

Page 49: Java 8, mit Lambdas das hohe Lied des Functional Programming singen

� Wir erinnern uns, da war diese starre Anweisung:

� Stattdessen können wir schreiben:

Lösungen…

logger.info( () -> "x: " + x + ", y: " + y );

logger.info("x: " + x + ", y: " + y);

� und dürfen hoffen, dass das java.util.Logging um das Angebot eines

Functional Interface erweitert ist

Java 8 - Lambda Expressions, IPS Expertenkreis, 03.07.2014 48

// Auszug Logging API; neue log Methode mit Lambda;

// wird und nur bei Bedarf ausgewertet!

public void log(Level level, Supplier<String> msgSupplier) {

if (!isLoggable(level)) {

return;

}

LogRecord lr = new LogRecord(level, msgSupplier.get());

Page 50: Java 8, mit Lambdas das hohe Lied des Functional Programming singen

� und was ist mit der Parallelisierung?

� Da bietet die Stream API vielfältige Angebote, z.B.

Lösungen…

for (BusinessObj b : listOfBO)

b.doComplexWork();

� Da bietet die Stream API vielfältige Angebote, z.B.

Java 8 - Lambda Expressions, IPS Expertenkreis, 03.07.2014 49

listOfBO.parllelStream().forEach(b.doComplexWork());

Page 51: Java 8, mit Lambdas das hohe Lied des Functional Programming singen

� und schlussendlich unser hässlicher ActionListener?

Lösungen…

saveButton.addActionListener(new ActionListener() {

@Override

public void actionPerformed(ActionEvent e) {

saveActions(e.getActionCommand());

}

});

� Da hilft eine simple (!!) Lambda Expression

Java 8 - Lambda Expressions, IPS Expertenkreis, 03.07.2014 50

});

saveButton.addActionListener(

e-> saveActions(e.getActionCommand()));

Page 52: Java 8, mit Lambdas das hohe Lied des Functional Programming singen

Fazit

� Lambda Expressions sind seit den Generics aus Java 5 die

gravierendste Neuerung in Java 8

� Führen das Prinzip des "Functional Programming“ in die Java-Welt ein

� Mit der Stream-API hat ORACLE/SUN eine leistungsfähige Innovation

Lambda Expression eröffnen ein neues Programmierprinzipin Java, was durchaus als Bereicherung anzusehen ist

51Java 8 - Lambda Expressions, IPS Expertenkreis, 03.07.2014

� Mit der Stream-API hat ORACLE/SUN eine leistungsfähige Innovation

des Collection Frameworks vorgenommen

� unter starker Nutzung von Lambda Expressions

Page 53: Java 8, mit Lambdas das hohe Lied des Functional Programming singen

Zentrale Paderborn

Westernmauer 12 - 16

33098 Paderborn

Tel.: 05251 1063-0

Seminarzentrum Wiesbaden

Kreuzberger Ring 13

65205 Wiesbaden

Vielen Dank für Ihre Aufmerksamkeit!

65205 Wiesbaden

Tel.: 0611 77840-00

Zentrales Fax:

0180 1 67349 0

0180 1 ORDIX 0

Weitere Geschäftsstellen

in Köln, Münster und Neu-Ulm

E-Mail: [email protected]

Internet: http://www.ordix.de