Behandling av elementer med foreach()-metoden
Du er allerede kjent med forEach()-metoden siden du har brukt den i praksis for å skrive ut hvert element i en samling til konsollen. La oss se nærmere på den og utforske dens implementasjoner.
Den gir en praktisk måte å behandle data på i en funksjonell stil. Det er imidlertid viktig å merke seg at rekkefølgen på behandlingen avhenger av strømtypen og metoden som brukes.
Det finnes to implementasjoner av forEach()-metoden i Stream API. La oss gå gjennom dem én etter én.
forEach-metode
Utfører en handling på hvert element, men rekkefølgen på behandlingen er ikke garantert i parallelle strømmer.
void forEach(Consumer<? super T> action)
Metoden forEach() tar en Consumer<T> som argument—et funksjonelt grensesnitt som definerer en operasjon for hvert element i strømmen. Den brukes ofte til logging, utskrift eller for å utføre sideeffekter.
Praktisk eksempel
I en nettbutikk må brukere motta varsler om personlige rabatter. Siden rekkefølgen ikke er viktig, brukes forEach() med en parallell strøm for raskere utførelse.
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 } }
Denne koden simulerer utsending av personlige rabatt-e-poster til kunder. Siden parallelStream() brukes, sendes e-postene i vilkårlig rekkefølge for bedre hastighet. Metoden forEach() anvender den angitte handlingen på hver e-post.
forEachOrdered-metoden
Utfører en handling samtidig som rekkefølgen på elementene bevares, selv i parallelle strømmer.
void forEachOrdered(Consumer<? super T> action)
Som forEach, aksepterer denne metoden også en Consumer<T>, men den sikrer at elementene behandles i samme rekkefølge som de vises i den opprinnelige strømmen. Dette er nyttig når det er avgjørende å opprettholde sekvensen.
Praktisk eksempel
Tenk deg et betalingssystem hvor hver transaksjon må behandles i nøyaktig den rekkefølgen den ankommer. Hvis betalinger håndteres utenfor rekkefølge, kan det føre til feil, som feilaktige saldo-beregninger.
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); } }
Denne koden simulerer et betalingsbehandlingssystem hvor transaksjoner må håndteres i den rekkefølgen de ankommer. Bruken av parallelStream() øker ytelsen, men forEachOrdered() sikrer at sekvensen forblir intakt.
Ytelsessammenligning: forEach() vs. forEachOrdered()
Mål hvor mye raskere forEach() utføres sammenlignet med forEachOrdered() ved bruk av parallelle strømmer. For å gjøre dette, opprett en liste med 10 millioner elementer, prosesser dem med begge metoder ved å beregne kvadratroten av hvert tall, og registrer kjøretiden.
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); } }
Metoden forEach() behandler elementer uten å bevare rekkefølgen, noe som gjør at strømmen fritt kan fordele oppgaver på tilgjengelige prosessor-kjerner. Dette maksimerer ytelsen, siden hver tråd kan hente elementer i vilkårlig rekkefølge og behandle dem parallelt uten begrensninger.
Metoden forEachOrdered() bevarer den opprinnelige rekkefølgen til elementene, noe som krever ekstra synkronisering. I en parallell strøm deles elementene først opp i deler for behandling, men resultatene må deretter settes sammen igjen i riktig rekkefølge før de sendes til behandlingsmetoden.
1. Hvilket funksjonelt grensesnitt aksepterer forEach-metoden?
2. Hvilket utskrift kan denne koden produsere?
Takk for tilbakemeldingene dine!
Spør AI
Spør AI
Spør om hva du vil, eller prøv ett av de foreslåtte spørsmålene for å starte chatten vår
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
Behandling av elementer med foreach()-metoden
Sveip for å vise menyen
Du er allerede kjent med forEach()-metoden siden du har brukt den i praksis for å skrive ut hvert element i en samling til konsollen. La oss se nærmere på den og utforske dens implementasjoner.
Den gir en praktisk måte å behandle data på i en funksjonell stil. Det er imidlertid viktig å merke seg at rekkefølgen på behandlingen avhenger av strømtypen og metoden som brukes.
Det finnes to implementasjoner av forEach()-metoden i Stream API. La oss gå gjennom dem én etter én.
forEach-metode
Utfører en handling på hvert element, men rekkefølgen på behandlingen er ikke garantert i parallelle strømmer.
void forEach(Consumer<? super T> action)
Metoden forEach() tar en Consumer<T> som argument—et funksjonelt grensesnitt som definerer en operasjon for hvert element i strømmen. Den brukes ofte til logging, utskrift eller for å utføre sideeffekter.
Praktisk eksempel
I en nettbutikk må brukere motta varsler om personlige rabatter. Siden rekkefølgen ikke er viktig, brukes forEach() med en parallell strøm for raskere utførelse.
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 } }
Denne koden simulerer utsending av personlige rabatt-e-poster til kunder. Siden parallelStream() brukes, sendes e-postene i vilkårlig rekkefølge for bedre hastighet. Metoden forEach() anvender den angitte handlingen på hver e-post.
forEachOrdered-metoden
Utfører en handling samtidig som rekkefølgen på elementene bevares, selv i parallelle strømmer.
void forEachOrdered(Consumer<? super T> action)
Som forEach, aksepterer denne metoden også en Consumer<T>, men den sikrer at elementene behandles i samme rekkefølge som de vises i den opprinnelige strømmen. Dette er nyttig når det er avgjørende å opprettholde sekvensen.
Praktisk eksempel
Tenk deg et betalingssystem hvor hver transaksjon må behandles i nøyaktig den rekkefølgen den ankommer. Hvis betalinger håndteres utenfor rekkefølge, kan det føre til feil, som feilaktige saldo-beregninger.
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); } }
Denne koden simulerer et betalingsbehandlingssystem hvor transaksjoner må håndteres i den rekkefølgen de ankommer. Bruken av parallelStream() øker ytelsen, men forEachOrdered() sikrer at sekvensen forblir intakt.
Ytelsessammenligning: forEach() vs. forEachOrdered()
Mål hvor mye raskere forEach() utføres sammenlignet med forEachOrdered() ved bruk av parallelle strømmer. For å gjøre dette, opprett en liste med 10 millioner elementer, prosesser dem med begge metoder ved å beregne kvadratroten av hvert tall, og registrer kjøretiden.
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); } }
Metoden forEach() behandler elementer uten å bevare rekkefølgen, noe som gjør at strømmen fritt kan fordele oppgaver på tilgjengelige prosessor-kjerner. Dette maksimerer ytelsen, siden hver tråd kan hente elementer i vilkårlig rekkefølge og behandle dem parallelt uten begrensninger.
Metoden forEachOrdered() bevarer den opprinnelige rekkefølgen til elementene, noe som krever ekstra synkronisering. I en parallell strøm deles elementene først opp i deler for behandling, men resultatene må deretter settes sammen igjen i riktig rekkefølge før de sendes til behandlingsmetoden.
1. Hvilket funksjonelt grensesnitt aksepterer forEach-metoden?
2. Hvilket utskrift kan denne koden produsere?
Takk for tilbakemeldingene dine!