Notice: This page requires JavaScript to function properly.
Please enable JavaScript in your browser settings or update your browser.
Lernen Verarbeitung von Elementen mit der ForEach()-Methode | Terminaloperationen in der Stream-API
Stream-API

bookVerarbeitung von Elementen mit der ForEach()-Methode

Sie sind bereits mit der Methode forEach() vertraut, da Sie sie in der Praxis verwendet haben, um jedes Element einer Collection auf der Konsole auszugeben. Werfen wir einen genaueren Blick darauf und untersuchen ihre Implementierungen.

Sie bietet eine komfortable Möglichkeit, Daten im funktionalen Stil zu verarbeiten. Es ist jedoch wichtig zu beachten, dass die Verarbeitungsreihenfolge vom Stream-Typ und der verwendeten Methode abhängt.

Im Stream API gibt es zwei Implementierungen der Methode forEach(). Gehen wir sie einzeln durch.

forEach-Methode

Führt eine Aktion für jedes Element aus, aber die Verarbeitungsreihenfolge ist bei parallelen Streams nicht garantiert.

void forEach(Consumer<? super T> action)

Die Methode forEach() nimmt einen Consumer<T> als Argument—eine funktionale Schnittstelle, die eine Operation für jedes Element im Stream definiert. Häufig verwendet für Protokollierung, Ausgabe oder das Ausführen von Seiteneffekten.

Praktisches Beispiel

In einem Online-Shop müssen Nutzer Benachrichtigungen über personalisierte Rabatte erhalten. Da die Reihenfolge keine Rolle spielt, wird forEach() mit einem parallelen Stream für schnellere Ausführung verwendet.

Main.java

Main.java

copy
1234567891011121314151617181920212223
package com.example; import java.util.List; import java.util.stream.Stream; public class Main { public static void main(String[] args) { List<String> customers = List.of( "alice@example.com", "bob@example.com", "charlie@example.com" ); // Parallel stream for faster processing Stream<String> customerStream = customers.parallelStream(); customerStream.forEach(email -> sendDiscountEmail(email)); } private static void sendDiscountEmail(String email) { System.out.println("Sending discount email to: " + email); // Simulating email sending process } }

Dieser Code simuliert das Versenden von personalisierten Rabatt-E-Mails an Kunden. Da parallelStream() verwendet wird, werden die E-Mails in beliebiger Reihenfolge für höhere Geschwindigkeit versendet. Die Methode forEach() wendet die angegebene Aktion auf jede E-Mail an.

forEachOrdered-Methode

Führt eine Aktion aus und bewahrt die Reihenfolge der Elemente, selbst in parallelen Streams.

void forEachOrdered(Consumer<? super T> action)

Wie forEach akzeptiert auch diese Methode einen Consumer<T>, stellt jedoch sicher, dass Elemente in der gleichen Reihenfolge verarbeitet werden, in der sie im ursprünglichen Stream erscheinen. Dies ist nützlich, wenn das Einhalten der Sequenz entscheidend ist.

Praktisches Beispiel

Stellen Sie sich ein Zahlungssystem vor, bei dem jede Transaktion genau in der Reihenfolge verarbeitet werden muss, in der sie eingeht. Wenn Zahlungen außerhalb der Reihenfolge bearbeitet werden, kann dies zu Fehlern führen, wie beispielsweise falschen Kontostandsberechnungen.

Main.java

Main.java

copy
123456789101112131415161718192021
package com.example; import java.util.List; import java.util.stream.Stream; public class Main { public static void main(String[] args) { List<String> payments = List.of( "Payment #5001 - $100", "Payment #5002 - $250", "Payment #5003 - $75" ); Stream<String> paymentStream = payments.parallelStream(); paymentStream.forEachOrdered(payment -> processPayment(payment)); } private static void processPayment(String payment) { System.out.println("Processing payment: " + payment); } }

Dieser Code simuliert ein Zahlungsverarbeitungssystem, bei dem Transaktionen in der Reihenfolge bearbeitet werden müssen, in der sie eintreffen. Die Verwendung von parallelStream() steigert die Leistung, aber forEachOrdered() stellt sicher, dass die Reihenfolge erhalten bleibt.

Leistungsvergleich: forEach() vs. forEachOrdered()

Vergleich der Ausführungsgeschwindigkeit von forEach() und forEachOrdered() bei der Arbeit mit parallelen Streams. Dazu wird eine Liste mit 10 Millionen Elementen erstellt, diese mit beiden Methoden verarbeitet, indem die Quadratwurzel jeder Zahl berechnet wird, und die Ausführungszeit gemessen.

Main.java

Main.java

copy
12345678910111213141516171819202122232425262728293031
package com.example; import java.util.List; import java.util.stream.IntStream; import java.util.ArrayList; public class Main { public static void main(String[] args) { List<Integer> numbers = new ArrayList<>(); IntStream.range(0, 10_000_000).forEach(numbers::add); // Create a list with 10 million elements // Measure execution time of `forEach()` long startTime = System.nanoTime(); numbers.parallelStream().forEach(num -> process(num)); long forEachTime = System.nanoTime() - startTime; // Measure execution time of `forEachOrdered()` startTime = System.nanoTime(); numbers.parallelStream().forEachOrdered(num -> process(num)); long forEachOrderedTime = System.nanoTime() - startTime; // Print results System.out.println("forEach execution time: " + forEachTime / 1_000_000 + " ms"); System.out.println("forEachOrdered execution time: " + forEachOrderedTime / 1_000_000 + " ms"); } private static void process(int num) { // Simulate workload Math.sqrt(num); } }

Die Methode forEach() verarbeitet Elemente ohne Reihenfolge zu bewahren, sodass der Stream die Aufgaben frei auf die verfügbaren Prozessorkerne verteilen kann. Dies maximiert die Leistung, da jeder Thread Elemente in beliebiger Reihenfolge auswählen und parallel ohne Einschränkungen verarbeiten kann.

Die Methode forEachOrdered() bewahrt die ursprüngliche Reihenfolge der Elemente, was zusätzliche Synchronisation erfordert. In einem parallelen Stream werden Elemente zunächst in Blöcke zur Verarbeitung aufgeteilt, aber ihre Ergebnisse müssen anschließend in der richtigen Reihenfolge wieder zusammengesetzt werden, bevor sie an die Verarbeitungsmethode übergeben werden.

1. Welches funktionale Interface akzeptiert die Methode forEach?

2. Welche Ausgabe kann dieser Code erzeugen?

question mark

Welches funktionale Interface akzeptiert die Methode forEach?

Select the correct answer

question mark

Welche Ausgabe kann dieser Code erzeugen?

Select the correct answer

War alles klar?

Wie können wir es verbessern?

Danke für Ihr Feedback!

Abschnitt 3. Kapitel 4

Fragen Sie AI

expand

Fragen Sie AI

ChatGPT

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

Suggested prompts:

Can you explain the main differences between forEach() and forEachOrdered()?

When should I use forEachOrdered() instead of forEach()?

Can you provide more real-world examples where order matters?

Awesome!

Completion rate improved to 2.33

bookVerarbeitung von Elementen mit der ForEach()-Methode

Swipe um das Menü anzuzeigen

Sie sind bereits mit der Methode forEach() vertraut, da Sie sie in der Praxis verwendet haben, um jedes Element einer Collection auf der Konsole auszugeben. Werfen wir einen genaueren Blick darauf und untersuchen ihre Implementierungen.

Sie bietet eine komfortable Möglichkeit, Daten im funktionalen Stil zu verarbeiten. Es ist jedoch wichtig zu beachten, dass die Verarbeitungsreihenfolge vom Stream-Typ und der verwendeten Methode abhängt.

Im Stream API gibt es zwei Implementierungen der Methode forEach(). Gehen wir sie einzeln durch.

forEach-Methode

Führt eine Aktion für jedes Element aus, aber die Verarbeitungsreihenfolge ist bei parallelen Streams nicht garantiert.

void forEach(Consumer<? super T> action)

Die Methode forEach() nimmt einen Consumer<T> als Argument—eine funktionale Schnittstelle, die eine Operation für jedes Element im Stream definiert. Häufig verwendet für Protokollierung, Ausgabe oder das Ausführen von Seiteneffekten.

Praktisches Beispiel

In einem Online-Shop müssen Nutzer Benachrichtigungen über personalisierte Rabatte erhalten. Da die Reihenfolge keine Rolle spielt, wird forEach() mit einem parallelen Stream für schnellere Ausführung verwendet.

Main.java

Main.java

copy
1234567891011121314151617181920212223
package com.example; import java.util.List; import java.util.stream.Stream; public class Main { public static void main(String[] args) { List<String> customers = List.of( "alice@example.com", "bob@example.com", "charlie@example.com" ); // Parallel stream for faster processing Stream<String> customerStream = customers.parallelStream(); customerStream.forEach(email -> sendDiscountEmail(email)); } private static void sendDiscountEmail(String email) { System.out.println("Sending discount email to: " + email); // Simulating email sending process } }

Dieser Code simuliert das Versenden von personalisierten Rabatt-E-Mails an Kunden. Da parallelStream() verwendet wird, werden die E-Mails in beliebiger Reihenfolge für höhere Geschwindigkeit versendet. Die Methode forEach() wendet die angegebene Aktion auf jede E-Mail an.

forEachOrdered-Methode

Führt eine Aktion aus und bewahrt die Reihenfolge der Elemente, selbst in parallelen Streams.

void forEachOrdered(Consumer<? super T> action)

Wie forEach akzeptiert auch diese Methode einen Consumer<T>, stellt jedoch sicher, dass Elemente in der gleichen Reihenfolge verarbeitet werden, in der sie im ursprünglichen Stream erscheinen. Dies ist nützlich, wenn das Einhalten der Sequenz entscheidend ist.

Praktisches Beispiel

Stellen Sie sich ein Zahlungssystem vor, bei dem jede Transaktion genau in der Reihenfolge verarbeitet werden muss, in der sie eingeht. Wenn Zahlungen außerhalb der Reihenfolge bearbeitet werden, kann dies zu Fehlern führen, wie beispielsweise falschen Kontostandsberechnungen.

Main.java

Main.java

copy
123456789101112131415161718192021
package com.example; import java.util.List; import java.util.stream.Stream; public class Main { public static void main(String[] args) { List<String> payments = List.of( "Payment #5001 - $100", "Payment #5002 - $250", "Payment #5003 - $75" ); Stream<String> paymentStream = payments.parallelStream(); paymentStream.forEachOrdered(payment -> processPayment(payment)); } private static void processPayment(String payment) { System.out.println("Processing payment: " + payment); } }

Dieser Code simuliert ein Zahlungsverarbeitungssystem, bei dem Transaktionen in der Reihenfolge bearbeitet werden müssen, in der sie eintreffen. Die Verwendung von parallelStream() steigert die Leistung, aber forEachOrdered() stellt sicher, dass die Reihenfolge erhalten bleibt.

Leistungsvergleich: forEach() vs. forEachOrdered()

Vergleich der Ausführungsgeschwindigkeit von forEach() und forEachOrdered() bei der Arbeit mit parallelen Streams. Dazu wird eine Liste mit 10 Millionen Elementen erstellt, diese mit beiden Methoden verarbeitet, indem die Quadratwurzel jeder Zahl berechnet wird, und die Ausführungszeit gemessen.

Main.java

Main.java

copy
12345678910111213141516171819202122232425262728293031
package com.example; import java.util.List; import java.util.stream.IntStream; import java.util.ArrayList; public class Main { public static void main(String[] args) { List<Integer> numbers = new ArrayList<>(); IntStream.range(0, 10_000_000).forEach(numbers::add); // Create a list with 10 million elements // Measure execution time of `forEach()` long startTime = System.nanoTime(); numbers.parallelStream().forEach(num -> process(num)); long forEachTime = System.nanoTime() - startTime; // Measure execution time of `forEachOrdered()` startTime = System.nanoTime(); numbers.parallelStream().forEachOrdered(num -> process(num)); long forEachOrderedTime = System.nanoTime() - startTime; // Print results System.out.println("forEach execution time: " + forEachTime / 1_000_000 + " ms"); System.out.println("forEachOrdered execution time: " + forEachOrderedTime / 1_000_000 + " ms"); } private static void process(int num) { // Simulate workload Math.sqrt(num); } }

Die Methode forEach() verarbeitet Elemente ohne Reihenfolge zu bewahren, sodass der Stream die Aufgaben frei auf die verfügbaren Prozessorkerne verteilen kann. Dies maximiert die Leistung, da jeder Thread Elemente in beliebiger Reihenfolge auswählen und parallel ohne Einschränkungen verarbeiten kann.

Die Methode forEachOrdered() bewahrt die ursprüngliche Reihenfolge der Elemente, was zusätzliche Synchronisation erfordert. In einem parallelen Stream werden Elemente zunächst in Blöcke zur Verarbeitung aufgeteilt, aber ihre Ergebnisse müssen anschließend in der richtigen Reihenfolge wieder zusammengesetzt werden, bevor sie an die Verarbeitungsmethode übergeben werden.

1. Welches funktionale Interface akzeptiert die Methode forEach?

2. Welche Ausgabe kann dieser Code erzeugen?

question mark

Welches funktionale Interface akzeptiert die Methode forEach?

Select the correct answer

question mark

Welche Ausgabe kann dieser Code erzeugen?

Select the correct answer

War alles klar?

Wie können wir es verbessern?

Danke für Ihr Feedback!

Abschnitt 3. Kapitel 4
some-alt