Rheinwerk Computing < openbook >


 
Inhaltsverzeichnis
Materialien
Vorwort
1 Java ist auch eine Sprache
2 Imperative Sprachkonzepte
3 Klassen und Objekte
4 Arrays und ihre Anwendungen
5 Der Umgang mit Zeichenketten
6 Eigene Klassen schreiben
7 Objektorientierte Beziehungsfragen
8 Ausnahmen müssen sein
9 Geschachtelte Typen
10 Besondere Typen der Java SE
11 Generics<T>
12 Lambda-Ausdrücke und funktionale Programmierung
13 Architektur, Design und angewandte Objektorientierung
14 Java Platform Module System
15 Die Klassenbibliothek
16 Einführung in die nebenläufige Programmierung
17 Einführung in Datenstrukturen und Algorithmen
18 Einführung in grafische Oberflächen
19 Einführung in Dateien und Datenströme
20 Einführung ins Datenbankmanagement mit JDBC
21 Bits und Bytes, Mathematisches und Geld
22 Testen mit JUnit
23 Die Werkzeuge des JDK
A Java SE-Module und Paketübersicht
Stichwortverzeichnis


Download:

- Listings, ca. 2,7 MB


Buch bestellen
Ihre Meinung?



Spacer
<< zurück
Java ist auch eine Insel von Christian Ullenboom

Einführung, Ausbildung, Praxis
Buch: Java ist auch eine Insel


Java ist auch eine Insel

Pfeil12 Lambda-Ausdrücke und funktionale Programmierung
Pfeil12.1 Funktionale Schnittstellen und Lambda-Ausdrücke
Pfeil12.1.1 Klassen implementieren Schnittstellen
Pfeil12.1.2 Lambda-Ausdrücke implementieren Schnittstellen
Pfeil12.1.3 Funktionale Schnittstellen
Pfeil12.1.4 Der Typ eines Lambda-Ausdrucks ergibt sich durch den Zieltyp
Pfeil12.1.5 Annotation @FunctionalInterface
Pfeil12.1.6 Syntax für Lambda-Ausdrücke
Pfeil12.1.7 Die Umgebung der Lambda-Ausdrücke und Variablenzugriffe
Pfeil12.1.8 Ausnahmen in Lambda-Ausdrücken
Pfeil12.1.9 Klassen mit einer abstrakten Methode als funktionale Schnittstelle? *
Pfeil12.2 Methodenreferenz
Pfeil12.2.1 Motivation
Pfeil12.2.2 Methodenreferenzen mit ::
Pfeil12.2.3 Varianten von Methodenreferenzen
Pfeil12.3 Konstruktorreferenz
Pfeil12.3.1 Parameterlose und parametrisierte Konstruktoren
Pfeil12.3.2 Nützliche vordefinierte Schnittstellen für Konstruktorreferenzen
Pfeil12.4 Funktionale Programmierung
Pfeil12.4.1 Code = Daten
Pfeil12.4.2 Programmierparadigmen: imperativ oder deklarativ
Pfeil12.4.3 Das Wesen der funktionalen Programmierung
Pfeil12.4.4 Funktionale Programmierung und funktionale Programmiersprachen
Pfeil12.4.5 Funktionen höherer Ordnung am Beispiel von Comparator
Pfeil12.4.6 Lambda-Ausdrücke als Abbildungen bzw. Funktionen betrachten
Pfeil12.5 Funktionale Schnittstellen aus dem java.util.function-Paket
Pfeil12.5.1 Blöcke mit Code und die funktionale Schnittstelle Consumer
Pfeil12.5.2 Supplier
Pfeil12.5.3 Prädikate und java.util.function.Predicate
Pfeil12.5.4 Funktionen über die funktionale Schnittstelle java.util.function.Function
Pfeil12.5.5 Ein bisschen Bi …
Pfeil12.5.6 Funktionale Schnittstellen mit Primitiven
Pfeil12.6 Optional ist keine Nullnummer
Pfeil12.6.1 Einsatz von null
Pfeil12.6.2 Der Optional-Typ
Pfeil12.6.3 Primitive optionale Typen
Pfeil12.6.4 Erst mal funktional mit Optional
Pfeil12.6.5 Primitiv-Optionales mit speziellen OptionalXXX-Klassen
Pfeil12.7 Was ist jetzt so funktional?
Pfeil12.8 Zum Weiterlesen
 

Zum Seitenanfang

12.7    Was ist jetzt so funktional? Zur vorigen ÜberschriftZur nächsten Überschrift

Bisher wurde ein Großteil dieses Abschnitts darauf verwendet, die Typen aus dem java.util.function-Paket vorzustellen, also die funktionalen Schnittstellen, mit denen Entwickler Abbildungen in Java ausdrücken können. Sprechen wir nun allgemeiner von der funktionalen Programmierung und ihren Vorteilen.

Wiederverwertbarkeit

Zunächst einmal bieten Funktionen eine zusätzliche Ebene der Wiederverwertbarkeit von Code. Nehmen wir ein Prädikat wie:

Predicate<Path> exists = path -> Files.exists( path );

Dieses exists-Prädikat ist relativ einfach und lässt auch noch die Ausnahmebehandlung aus. Es könnte aber natürlich komplexer sein. Der Punkt ist, dass diese Prädikate an allen möglichen Stellen wiederverwendet werden können, etwa zum Filtern in Listen oder zum Löschen von Elementen aus Listen. Das Prädikat kann als Funktion weitergereicht oder zu neuen Prädikaten verbunden werden, etwa zu:

Predicate<Path> exists    = path -> Files.exists( path );

Predicate<Path> directory = path -> Files.isDirectory( path );

Predicate<Path> existsAndDirectory = exists.and( directory );

Methoden wie ifPresent(Predicate) oder removeIf(Predicate) nehmen dann dieses Prädikat und führen Operationen durch. Diese kleinen Mini-Objekte lassen sich sehr gut testen, und das minimiert insgesamt Fehler im Code.

Während aktuelle Bibliotheken wenig davon Gebrauch machen, Typen wie Supplier, Consumer, Function oder Predicate anzunehmen und zurückzugeben, wird sich dieses im Laufe der nächsten Jahre ändern.

Zustandslos, immutable

Bei der funktionalen Programmierung geht es darum, ohne externe Zustände auszukommen. Pure funktionale Programmiersprachen basieren auf puren Funktionen, und auch in Java muss nicht jede Methode einen äußeren Zustand verändern. Allerdings sind es Java-Entwickler gewohnt, in Zuständen zu denken, und daran ist an sich nichts Falsches: Ein Textdokument im Speicher ist eben ein Objektgraph genauso wie eine grafische Anwendung mit Eingabefeldern. Worauf funktionale Programmierung abzielt, sind die Operationen auf den Datenstrukturen und Berechnungen, die ohne Seiteneffekte sind.

Pure Funktionen ohne Zustand haben den Vorteil, dass sie

  • beliebig oft ausgeführt werden können, ohne dass sich Systemzustände ändern,

  • in beliebiger Reihenfolge ausgeführt werden können, ohne dass das Ergebnis ein anderes wird und

  • einfacher zu testen sind, als wenn es umfangreiche Zustandsänderungen gibt.

Diese Vorteile sind reizvoll unter dem Gesichtspunkt der Parallelisierung, denn die Prozessoren werden nicht wirklich schneller, aber wir haben mehr Prozessorkerne zur Verfügung. Pure Funktionen erlauben es Bibliotheken, Aufgaben wie Suchen und Filtern auf Kerne zu verteilen und auf diese Weise zu parallelisieren. Je weniger Zustand dabei im Spiel ist, desto besser, denn je weniger Zustand, desto weniger Synchronisation und Warteeffekte gibt es.

Aufpassen müssen Entwickler natürlich trotzdem, denn ein Lambda-Ausdruck muss nicht pur sein und kann Seiteneffekte haben. Daher ist es wichtig zu wissen, wann diese Lambda-Ausdrücke vielleicht nebenläufig sind und eine Synchronisation nötig ist.

[zB]  Beispiel

Die Schnittstelle Iterable deklariert eine Methode forEach(…), mit einem Parameter vom Typ einer funktionalen Schnittstelle. Hier ist ein Lambda-Ausdruck möglich. Es wäre natürlich grundlegend falsch, wenn dieser Lambda-Ausdruck selbst in die Sammlung eingreift:

List<Integer> ints = new ArrayList<>( Arrays.asList( 1, 99, 2 ) );

ints.forEach( v -> { System.out.println( ints + ", " + v); ints.set( v, 0 ); } );

Die Ausgabe ist weit von dem entfernt, was erwartet wurde, aber kein Wunder, wenn Lambda-Ausdrücke illegale Seiteneffekte hervorrufen:

[1, 99, 2], 1

[1, 0, 2], 0

[0, 0, 2], 2

Die Vermeidung von Zuständen, gekoppelt an die Unveränderbarkeit von Werten (engl. immutability), erhöht das Verständnis des Programms, da Entwickler es schwer haben, im Kopf das System mit den ganzen Änderungen »nachzuspielen«, insbesondere wenn diese Änderungen noch nebenläufig sind. Das zeigt das vorangehende Beispiel recht gut. Solche Systeme zu verstehen und zu debuggen ist schwer. Je weniger Seiteneffekte es gibt, desto einfacher ist das Programm zu verstehen. Zustände machen ein Programm komplex, nicht nur in nebenläufigen Umgebungen. Wenn die Methode pur ist, muss ein Entwickler nichts anderes tun, als den Code der Methode zu verstehen. Wenn die Methode von Zuständen des Objekts abhängt, muss ein Entwickler den Code der gesamten Klasse verstehen. Und wenn das Objekt von Zuständen im Gesamtprogramm abhängt, ufert das Ganze aus, denn dann muss man noch viel mehr vom System verstehen.

 


Ihre Meinung?

Wie hat Ihnen das Openbook gefallen? Wir freuen uns immer über Ihre Rückmeldung. Schreiben Sie uns gerne Ihr Feedback als E-Mail an kommunikation@rheinwerk-verlag.de

<< zurück
 Zum Rheinwerk-Shop
Zum Rheinwerk-Shop: Java ist auch eine Insel Java ist auch eine Insel

Jetzt Buch bestellen


 Buchempfehlungen
Zum Rheinwerk-Shop: Captain CiaoCiao erobert Java

Captain CiaoCiao erobert Java




Zum Rheinwerk-Shop: Java SE 9 Standard-Bibliothek

Java SE 9 Standard-Bibliothek




Zum Rheinwerk-Shop: Algorithmen in Java

Algorithmen in Java




Zum Rheinwerk-Shop: Objektorientierte Programmierung

Objektorientierte Programmierung




 Lieferung
Versandkostenfrei bestellen in Deutschland, Österreich und in die Schweiz

InfoInfo



 

 


Copyright © Rheinwerk Verlag GmbH 2021

Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das Openbook denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt.

Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.

 

[Rheinwerk Computing]



Rheinwerk Verlag GmbH, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, service@rheinwerk-verlag.de



Cookie-Einstellungen ändern