Bearbetning av element med forEach()-metoden
Du är redan bekant med metoden forEach() eftersom du har använt den i praktiken för att skriva ut varje element i en samling till konsolen. Låt oss titta närmare på den och utforska dess implementationer.
Den erbjuder ett bekvämt sätt att bearbeta data i en funktionell stil. Det är dock viktigt att notera att bearbetningsordningen beror på strömtypen och den använda metoden.
Det finns två implementationer av metoden forEach() i Stream API. Låt oss gå igenom dem en i taget.
forEach-metoden
Utför en åtgärd på varje element, men bearbetningsordningen garanteras inte i parallella strömmar.
void forEach(Consumer<? super T> action)
Metoden forEach() tar en Consumer<T> som argument—ett funktionellt gränssnitt som definierar en operation för varje element i strömmen. Den används ofta för loggning, utskrift eller för att utföra bieffekter.
Praktiskt exempel
I en webbutik behöver användare få notiser om personliga rabatter. Eftersom ordningen inte spelar någon roll används forEach() med en parallell ström för snabbare exekvering.
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 } }
Denna kod simulerar utskick av personliga rabattmejl till kunder. Eftersom parallelStream() används skickas mejlen i ingen särskild ordning för förbättrad hastighet. Metoden forEach() tillämpar den angivna åtgärden på varje mejl.
forEachOrdered-metoden
Utför en åtgärd samtidigt som ordningen på elementen bevaras, även i parallella strömmar.
void forEachOrdered(Consumer<? super T> action)
Precis som forEach accepterar denna metod också en Consumer<T>, men den säkerställer att elementen behandlas i samma ordning som de förekommer i den ursprungliga strömmen. Detta är användbart när det är avgörande att behålla sekvensen.
Praktiskt exempel
Föreställ dig ett betalningssystem där varje transaktion måste behandlas i exakt den ordning den anländer. Om betalningar hanteras i fel ordning kan det leda till fel, såsom felaktiga saldoberekingar.
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); } }
Denna kod simulerar ett betalningshanteringssystem där transaktioner måste behandlas i den ordning de anländer. Användningen av parallelStream() ökar prestandan, men forEachOrdered() säkerställer att sekvensen förblir intakt.
Prestandajämförelse: forEach() vs. forEachOrdered()
Låt oss mäta hur mycket snabbare forEach() körs jämfört med forEachOrdered() vid arbete med parallella strömmar. För att göra detta skapar du en lista med 10 miljoner element, behandlar dem med båda metoderna genom att beräkna kvadratroten av varje tal och registrerar exekveringstiden.
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); } }
forEach()-metoden bearbetar element utan att bevara ordningen, vilket gör att strömmen fritt kan fördela uppgifter över tillgängliga processorkärnor. Detta maximerar prestanda, eftersom varje tråd kan välja element i valfri ordning och bearbeta dem parallellt utan begränsningar.
Metoden forEachOrdered() bevarar ursprunglig ordning på elementen, vilket kräver ytterligare synkronisering. I en parallell ström delas elementen först upp i delar för bearbetning, men deras resultat måste sedan sättas ihop i rätt ordning innan de skickas vidare till bearbetningsmetoden.
1. Vilket funktionellt gränssnitt accepterar metoden forEach?
2. Vilket utdata kan denna kod producera?
Tack för dina kommentarer!
Fråga AI
Fråga AI
Fråga vad du vill eller prova någon av de föreslagna frågorna för att starta vårt samtal
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
Bearbetning av element med forEach()-metoden
Svep för att visa menyn
Du är redan bekant med metoden forEach() eftersom du har använt den i praktiken för att skriva ut varje element i en samling till konsolen. Låt oss titta närmare på den och utforska dess implementationer.
Den erbjuder ett bekvämt sätt att bearbeta data i en funktionell stil. Det är dock viktigt att notera att bearbetningsordningen beror på strömtypen och den använda metoden.
Det finns två implementationer av metoden forEach() i Stream API. Låt oss gå igenom dem en i taget.
forEach-metoden
Utför en åtgärd på varje element, men bearbetningsordningen garanteras inte i parallella strömmar.
void forEach(Consumer<? super T> action)
Metoden forEach() tar en Consumer<T> som argument—ett funktionellt gränssnitt som definierar en operation för varje element i strömmen. Den används ofta för loggning, utskrift eller för att utföra bieffekter.
Praktiskt exempel
I en webbutik behöver användare få notiser om personliga rabatter. Eftersom ordningen inte spelar någon roll används forEach() med en parallell ström för snabbare exekvering.
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 } }
Denna kod simulerar utskick av personliga rabattmejl till kunder. Eftersom parallelStream() används skickas mejlen i ingen särskild ordning för förbättrad hastighet. Metoden forEach() tillämpar den angivna åtgärden på varje mejl.
forEachOrdered-metoden
Utför en åtgärd samtidigt som ordningen på elementen bevaras, även i parallella strömmar.
void forEachOrdered(Consumer<? super T> action)
Precis som forEach accepterar denna metod också en Consumer<T>, men den säkerställer att elementen behandlas i samma ordning som de förekommer i den ursprungliga strömmen. Detta är användbart när det är avgörande att behålla sekvensen.
Praktiskt exempel
Föreställ dig ett betalningssystem där varje transaktion måste behandlas i exakt den ordning den anländer. Om betalningar hanteras i fel ordning kan det leda till fel, såsom felaktiga saldoberekingar.
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); } }
Denna kod simulerar ett betalningshanteringssystem där transaktioner måste behandlas i den ordning de anländer. Användningen av parallelStream() ökar prestandan, men forEachOrdered() säkerställer att sekvensen förblir intakt.
Prestandajämförelse: forEach() vs. forEachOrdered()
Låt oss mäta hur mycket snabbare forEach() körs jämfört med forEachOrdered() vid arbete med parallella strömmar. För att göra detta skapar du en lista med 10 miljoner element, behandlar dem med båda metoderna genom att beräkna kvadratroten av varje tal och registrerar exekveringstiden.
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); } }
forEach()-metoden bearbetar element utan att bevara ordningen, vilket gör att strömmen fritt kan fördela uppgifter över tillgängliga processorkärnor. Detta maximerar prestanda, eftersom varje tråd kan välja element i valfri ordning och bearbeta dem parallellt utan begränsningar.
Metoden forEachOrdered() bevarar ursprunglig ordning på elementen, vilket kräver ytterligare synkronisering. I en parallell ström delas elementen först upp i delar för bearbetning, men deras resultat måste sedan sättas ihop i rätt ordning innan de skickas vidare till bearbetningsmetoden.
1. Vilket funktionellt gränssnitt accepterar metoden forEach?
2. Vilket utdata kan denna kod producera?
Tack för dina kommentarer!