Notice: This page requires JavaScript to function properly.
Please enable JavaScript in your browser settings or update your browser.
Lernen Prinzipien | Grundlagen und Funktionale Möglichkeiten der Stream-API
Stream-API

bookPrinzipien

Die Prinzipien der Arbeit mit der Stream-API basieren auf den zentralen Konzepten der funktionalen Programmierung und der Lazy Evaluation. Im Folgenden werden die wichtigsten Prinzipien der Stream-API vorgestellt.

Lazy Evaluation

Eines der grundlegenden Prinzipien der Stream-API ist die Lazy Evaluation.

Das bedeutet, dass intermediäre Operationen wie filter() oder map() nicht sofort ausgeführt werden. Sie bilden lediglich eine Kette von Aktionen, die erst dann ausgeführt wird, wenn eine abschließende Operation wie collect() oder forEach() aufgerufen wird.

Main.java

Main.java

copy
12345678910111213
package com.example; import java.util.List; public class Main { public static void main(String[] args) { List<String> names = List.of("Alice", "Bob", "Charlie"); long count = names.stream() .filter(name -> name.startsWith("A")) // Forming the operation .count(); // Triggering execution System.out.println(count); // Output: 1 } }

Dieser Code erstellt einen Stream aus einer Liste von Strings, filtert die Elemente, sodass nur diejenigen erhalten bleiben, die mit dem Buchstaben A beginnen, und zählt, wie viele die Bedingung erfüllen. Das Ergebnis (1) wird ausgegeben, da nur Alice die Bedingung erfüllt.

Funktionaler Programmierstil

Die Stream API verwendet Lambda-Ausdrücke und funktionale Schnittstellen zur Datenverarbeitung. Anstelle des imperativen Ansatzes mit Schleifen wird beschrieben, was mit den Daten geschehen soll:

Main.java

Main.java

copy
1234567891011121314
package com.example; import java.util.List; public class Main { public static void main(String[] args) { List<String> fruits = List.of("apple", "banana", "cherry", "apricot", "blueberry"); List<String> result = fruits.stream() .map(String::toUpperCase) // Convert all strings to uppercase .skip(3) .toList(); // Collect the result into a new list System.out.println(result); } }

Dieser Code erstellt einen Stream aus einer Liste von Früchten, wandelt die Strings mit map() in Großbuchstaben um und überspringt mit skip() die ersten drei Elemente. Das Ergebnis wird in eine neue Liste gesammelt und ausgegeben, beginnend ab dem vierten Element.

Unveränderlichkeit der Daten

Die Stream API verändert die Originaldaten nicht. Alle Operationen erzeugen einen neuen Stream oder liefern ein Ergebnis zurück, ohne die Sammlung oder das Array zu verändern. Dies erhöht die Datensicherheit und verhindert unerwartete Nebeneffekte.

Main.java

Main.java

copy
12345678910111213
package com.example; import java.util.List; public class Main { public static void main(String[] args) { List<String> names = List.of("Alice", "Bob", "Charlie"); List<String> updateNames = names.stream() .filter(name -> name.startsWith("A")) .toList(); System.out.println(names); // Output: [Alice, Bob, Charlie] } }

Die Stream-API filtert die Listennamen, um einen neuen Stream updateNames zu erstellen, der nur Elemente enthält, die mit dem Buchstaben A beginnen. Die ursprüngliche Liste names bleibt jedoch unverändert, da die Stream-API die Daten nicht direkt verändert. Dies gewährleistet Datensicherheit und verhindert Nebenwirkungen.

Streams sind nur einmal konsumierbar

Ein Stream kann nur einmal verwendet werden. Nach Ausführung einer terminalen Operation steht der Stream für weitere Verarbeitung nicht mehr zur Verfügung.

Main.java

Main.java

copy
123456789101112
package com.example; import java.util.List; import java.util.stream.Stream; public class Main { public static void main(String[] args) { Stream<String> stream = List.of("Alice", "Bob").stream(); stream.forEach(System.out::println); stream.forEach(System.out::println); // Error: Stream has already been used } }

Hier wird ein Stream aus einer Liste von Strings erstellt und jedes Element auf die Konsole ausgegeben. Nachdem der Stream einmal verwendet wurde, kann er nicht wiederverwendet werden, was zu einem Fehler führt, wenn versucht wird, forEach() erneut aufzurufen.

Parallele Verarbeitung

Die Stream-API unterstützt parallele Streams und ermöglicht dadurch eine schnellere Datenverarbeitung auf Mehrkernsystemen. Dies wird ausführlicher hier behandelt.

Main.java

Main.java

copy
1234567891011
package com.example; import java.util.List; public class Main { public static void main(String[] args) { List<Integer> numbers = List.of(1, 2, 3, 4, 5); numbers.parallelStream() .forEach(System.out::println); // Elements are processed in parallel } }

Dieser Code erstellt einen parallelen Stream aus einer Liste von Zahlen und gibt jedes Element auf der Konsole aus. Die Verwendung von parallelStream() ermöglicht eine parallele Verarbeitung der Listenelemente, was die Ausführung beschleunigen kann, insbesondere bei großen Datenmengen.

Code-Sauberkeit und Lesbarkeit

Die Verwendung der Stream API macht den Code deklarativer. Anstatt zu beschreiben, wie eine Aufgabe ausgeführt werden soll (wie bei der Verwendung von Schleifen), wird beschrieben, was genau erledigt werden muss. Dies verbessert die Lesbarkeit und vereinfacht die Wartung des Codes.

Beispiel mit einer Schleife:

List<String> names = List.of("Alice", "Bob", "Charlie");
for (String name : names) {
    System.out.println(name);
}

Beispiel mit der Stream-API:

List<String> names = List.of("Alice", "Bob", "Charlie");
names.stream().forEach(System.out::println);

Im ersten Schleifenbeispiel wird explizit beschrieben, wie durch die Liste iteriert und die Elemente ausgegeben werden, während im zweiten Beispiel mit der Stream-API lediglich angegeben wird, was gemacht werden soll: Durchlaufen der Elemente und deren Ausgabe. Dadurch wird der Code deklarativer und lesbarer.

War alles klar?

Wie können wir es verbessern?

Danke für Ihr Feedback!

Abschnitt 1. Kapitel 2

Fragen Sie AI

expand

Fragen Sie AI

ChatGPT

Fragen Sie alles oder probieren Sie eine der vorgeschlagenen Fragen, um unser Gespräch zu beginnen

Awesome!

Completion rate improved to 2.33

bookPrinzipien

Swipe um das Menü anzuzeigen

Die Prinzipien der Arbeit mit der Stream-API basieren auf den zentralen Konzepten der funktionalen Programmierung und der Lazy Evaluation. Im Folgenden werden die wichtigsten Prinzipien der Stream-API vorgestellt.

Lazy Evaluation

Eines der grundlegenden Prinzipien der Stream-API ist die Lazy Evaluation.

Das bedeutet, dass intermediäre Operationen wie filter() oder map() nicht sofort ausgeführt werden. Sie bilden lediglich eine Kette von Aktionen, die erst dann ausgeführt wird, wenn eine abschließende Operation wie collect() oder forEach() aufgerufen wird.

Main.java

Main.java

copy
12345678910111213
package com.example; import java.util.List; public class Main { public static void main(String[] args) { List<String> names = List.of("Alice", "Bob", "Charlie"); long count = names.stream() .filter(name -> name.startsWith("A")) // Forming the operation .count(); // Triggering execution System.out.println(count); // Output: 1 } }

Dieser Code erstellt einen Stream aus einer Liste von Strings, filtert die Elemente, sodass nur diejenigen erhalten bleiben, die mit dem Buchstaben A beginnen, und zählt, wie viele die Bedingung erfüllen. Das Ergebnis (1) wird ausgegeben, da nur Alice die Bedingung erfüllt.

Funktionaler Programmierstil

Die Stream API verwendet Lambda-Ausdrücke und funktionale Schnittstellen zur Datenverarbeitung. Anstelle des imperativen Ansatzes mit Schleifen wird beschrieben, was mit den Daten geschehen soll:

Main.java

Main.java

copy
1234567891011121314
package com.example; import java.util.List; public class Main { public static void main(String[] args) { List<String> fruits = List.of("apple", "banana", "cherry", "apricot", "blueberry"); List<String> result = fruits.stream() .map(String::toUpperCase) // Convert all strings to uppercase .skip(3) .toList(); // Collect the result into a new list System.out.println(result); } }

Dieser Code erstellt einen Stream aus einer Liste von Früchten, wandelt die Strings mit map() in Großbuchstaben um und überspringt mit skip() die ersten drei Elemente. Das Ergebnis wird in eine neue Liste gesammelt und ausgegeben, beginnend ab dem vierten Element.

Unveränderlichkeit der Daten

Die Stream API verändert die Originaldaten nicht. Alle Operationen erzeugen einen neuen Stream oder liefern ein Ergebnis zurück, ohne die Sammlung oder das Array zu verändern. Dies erhöht die Datensicherheit und verhindert unerwartete Nebeneffekte.

Main.java

Main.java

copy
12345678910111213
package com.example; import java.util.List; public class Main { public static void main(String[] args) { List<String> names = List.of("Alice", "Bob", "Charlie"); List<String> updateNames = names.stream() .filter(name -> name.startsWith("A")) .toList(); System.out.println(names); // Output: [Alice, Bob, Charlie] } }

Die Stream-API filtert die Listennamen, um einen neuen Stream updateNames zu erstellen, der nur Elemente enthält, die mit dem Buchstaben A beginnen. Die ursprüngliche Liste names bleibt jedoch unverändert, da die Stream-API die Daten nicht direkt verändert. Dies gewährleistet Datensicherheit und verhindert Nebenwirkungen.

Streams sind nur einmal konsumierbar

Ein Stream kann nur einmal verwendet werden. Nach Ausführung einer terminalen Operation steht der Stream für weitere Verarbeitung nicht mehr zur Verfügung.

Main.java

Main.java

copy
123456789101112
package com.example; import java.util.List; import java.util.stream.Stream; public class Main { public static void main(String[] args) { Stream<String> stream = List.of("Alice", "Bob").stream(); stream.forEach(System.out::println); stream.forEach(System.out::println); // Error: Stream has already been used } }

Hier wird ein Stream aus einer Liste von Strings erstellt und jedes Element auf die Konsole ausgegeben. Nachdem der Stream einmal verwendet wurde, kann er nicht wiederverwendet werden, was zu einem Fehler führt, wenn versucht wird, forEach() erneut aufzurufen.

Parallele Verarbeitung

Die Stream-API unterstützt parallele Streams und ermöglicht dadurch eine schnellere Datenverarbeitung auf Mehrkernsystemen. Dies wird ausführlicher hier behandelt.

Main.java

Main.java

copy
1234567891011
package com.example; import java.util.List; public class Main { public static void main(String[] args) { List<Integer> numbers = List.of(1, 2, 3, 4, 5); numbers.parallelStream() .forEach(System.out::println); // Elements are processed in parallel } }

Dieser Code erstellt einen parallelen Stream aus einer Liste von Zahlen und gibt jedes Element auf der Konsole aus. Die Verwendung von parallelStream() ermöglicht eine parallele Verarbeitung der Listenelemente, was die Ausführung beschleunigen kann, insbesondere bei großen Datenmengen.

Code-Sauberkeit und Lesbarkeit

Die Verwendung der Stream API macht den Code deklarativer. Anstatt zu beschreiben, wie eine Aufgabe ausgeführt werden soll (wie bei der Verwendung von Schleifen), wird beschrieben, was genau erledigt werden muss. Dies verbessert die Lesbarkeit und vereinfacht die Wartung des Codes.

Beispiel mit einer Schleife:

List<String> names = List.of("Alice", "Bob", "Charlie");
for (String name : names) {
    System.out.println(name);
}

Beispiel mit der Stream-API:

List<String> names = List.of("Alice", "Bob", "Charlie");
names.stream().forEach(System.out::println);

Im ersten Schleifenbeispiel wird explizit beschrieben, wie durch die Liste iteriert und die Elemente ausgegeben werden, während im zweiten Beispiel mit der Stream-API lediglich angegeben wird, was gemacht werden soll: Durchlaufen der Elemente und deren Ausgabe. Dadurch wird der Code deklarativer und lesbarer.

War alles klar?

Wie können wir es verbessern?

Danke für Ihr Feedback!

Abschnitt 1. Kapitel 2
some-alt