Elementen Verwerken met de forEach()-Methode
Je bent al bekend met de methode forEach() omdat je deze in de praktijk hebt gebruikt om elk element van een collectie naar de console te printen. Laten we deze methode nader bekijken en de implementaties ervan verkennen.
Deze methode biedt een handige manier om gegevens op een functionele wijze te verwerken. Het is echter belangrijk op te merken dat de verwerkingsvolgorde afhankelijk is van het type stream en de gebruikte methode.
Er zijn twee implementaties van de methode forEach() in de Stream API. Laten we ze één voor één doornemen.
forEach-methode
Voert een actie uit op elk element, maar de verwerkingsvolgorde is niet gegarandeerd bij parallelle streams.
void forEach(Consumer<? super T> action)
De methode forEach() accepteert een Consumer<T> als argument—een functionele interface die een bewerking definieert voor elk element in de stream. Wordt vaak gebruikt voor logging, afdrukken of het uitvoeren van neveneffecten.
Praktisch voorbeeld
In een webwinkel moeten gebruikers meldingen ontvangen over gepersonaliseerde kortingen. Omdat de volgorde niet van belang is, wordt forEach() gebruikt met een parallelle stream voor snellere uitvoering.
Main.java
1234567891011121314151617181920212223package 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 } }
Deze code simuleert het verzenden van gepersonaliseerde kortingsmails naar klanten. Omdat parallelStream() wordt gebruikt, worden e-mails in willekeurige volgorde verzonden voor verbeterde snelheid. De methode forEach() past de opgegeven actie toe op elk e-mailadres.
forEachOrdered-methode
Voert een actie uit met behoud van de volgorde van elementen, zelfs in parallelle streams.
void forEachOrdered(Consumer<? super T> action)
Net als forEach accepteert deze methode ook een Consumer<T>, maar zij garandeert dat elementen worden verwerkt in dezelfde volgorde als waarin ze in de oorspronkelijke stream voorkomen. Dit is nuttig wanneer het behouden van de volgorde essentieel is.
Praktisch voorbeeld
Stel een betalingssysteem voor waarin elke transactie exact in de volgorde van binnenkomst moet worden verwerkt. Als betalingen buiten de volgorde worden afgehandeld, kan dit leiden tot fouten, zoals onjuiste saldo-berekeningen.
Main.java
123456789101112131415161718192021package 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); } }
Deze code simuleert een betalingsverwerkingssysteem waarbij transacties in de volgorde van binnenkomst moeten worden afgehandeld. Het gebruik van parallelStream() verhoogt de prestaties, maar forEachOrdered() zorgt ervoor dat de volgorde behouden blijft.
Prestatievergelijking: forEach() vs. forEachOrdered()
Hier wordt gemeten hoe veel sneller forEach() wordt uitgevoerd in vergelijking met forEachOrdered() bij het werken met parallelle streams. Hiervoor wordt een lijst van 10 miljoen elementen aangemaakt, verwerkt met beide methoden door de vierkantswortel van elk getal te berekenen, en de uitvoeringstijd geregistreerd.
Main.java
12345678910111213141516171819202122232425262728293031package 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); } }
De methode forEach() verwerkt elementen zonder de volgorde te behouden, waardoor de stream de taken vrij kan verdelen over de beschikbare processorkernen. Dit maximaliseert de prestaties, omdat elke thread elementen in willekeurige volgorde kan oppakken en parallel kan verwerken zonder beperkingen.
De methode forEachOrdered() behoudt de oorspronkelijke volgorde van de elementen, wat extra synchronisatie vereist. In een parallelle stream worden elementen eerst opgesplitst in delen voor verwerking, maar hun resultaten moeten vervolgens in de juiste volgorde worden samengevoegd voordat ze aan de verwerkingsmethode worden doorgegeven.
1. Welke functionele interface accepteert de methode forEach?
2. Welke uitvoer kan deze code produceren?
Bedankt voor je feedback!
Vraag AI
Vraag AI
Vraag wat u wilt of probeer een van de voorgestelde vragen om onze chat te starten.
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
Elementen Verwerken met de forEach()-Methode
Veeg om het menu te tonen
Je bent al bekend met de methode forEach() omdat je deze in de praktijk hebt gebruikt om elk element van een collectie naar de console te printen. Laten we deze methode nader bekijken en de implementaties ervan verkennen.
Deze methode biedt een handige manier om gegevens op een functionele wijze te verwerken. Het is echter belangrijk op te merken dat de verwerkingsvolgorde afhankelijk is van het type stream en de gebruikte methode.
Er zijn twee implementaties van de methode forEach() in de Stream API. Laten we ze één voor één doornemen.
forEach-methode
Voert een actie uit op elk element, maar de verwerkingsvolgorde is niet gegarandeerd bij parallelle streams.
void forEach(Consumer<? super T> action)
De methode forEach() accepteert een Consumer<T> als argument—een functionele interface die een bewerking definieert voor elk element in de stream. Wordt vaak gebruikt voor logging, afdrukken of het uitvoeren van neveneffecten.
Praktisch voorbeeld
In een webwinkel moeten gebruikers meldingen ontvangen over gepersonaliseerde kortingen. Omdat de volgorde niet van belang is, wordt forEach() gebruikt met een parallelle stream voor snellere uitvoering.
Main.java
1234567891011121314151617181920212223package 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 } }
Deze code simuleert het verzenden van gepersonaliseerde kortingsmails naar klanten. Omdat parallelStream() wordt gebruikt, worden e-mails in willekeurige volgorde verzonden voor verbeterde snelheid. De methode forEach() past de opgegeven actie toe op elk e-mailadres.
forEachOrdered-methode
Voert een actie uit met behoud van de volgorde van elementen, zelfs in parallelle streams.
void forEachOrdered(Consumer<? super T> action)
Net als forEach accepteert deze methode ook een Consumer<T>, maar zij garandeert dat elementen worden verwerkt in dezelfde volgorde als waarin ze in de oorspronkelijke stream voorkomen. Dit is nuttig wanneer het behouden van de volgorde essentieel is.
Praktisch voorbeeld
Stel een betalingssysteem voor waarin elke transactie exact in de volgorde van binnenkomst moet worden verwerkt. Als betalingen buiten de volgorde worden afgehandeld, kan dit leiden tot fouten, zoals onjuiste saldo-berekeningen.
Main.java
123456789101112131415161718192021package 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); } }
Deze code simuleert een betalingsverwerkingssysteem waarbij transacties in de volgorde van binnenkomst moeten worden afgehandeld. Het gebruik van parallelStream() verhoogt de prestaties, maar forEachOrdered() zorgt ervoor dat de volgorde behouden blijft.
Prestatievergelijking: forEach() vs. forEachOrdered()
Hier wordt gemeten hoe veel sneller forEach() wordt uitgevoerd in vergelijking met forEachOrdered() bij het werken met parallelle streams. Hiervoor wordt een lijst van 10 miljoen elementen aangemaakt, verwerkt met beide methoden door de vierkantswortel van elk getal te berekenen, en de uitvoeringstijd geregistreerd.
Main.java
12345678910111213141516171819202122232425262728293031package 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); } }
De methode forEach() verwerkt elementen zonder de volgorde te behouden, waardoor de stream de taken vrij kan verdelen over de beschikbare processorkernen. Dit maximaliseert de prestaties, omdat elke thread elementen in willekeurige volgorde kan oppakken en parallel kan verwerken zonder beperkingen.
De methode forEachOrdered() behoudt de oorspronkelijke volgorde van de elementen, wat extra synchronisatie vereist. In een parallelle stream worden elementen eerst opgesplitst in delen voor verwerking, maar hun resultaten moeten vervolgens in de juiste volgorde worden samengevoegd voordat ze aan de verwerkingsmethode worden doorgegeven.
1. Welke functionele interface accepteert de methode forEach?
2. Welke uitvoer kan deze code produceren?
Bedankt voor je feedback!