Notice: This page requires JavaScript to function properly.
Please enable JavaScript in your browser settings or update your browser.
Oppiskele Alkioiden Käsittely Foreach()-Menetelmällä | Stream API:n Pääteoperaatiot
Stream API

bookAlkioiden Käsittely Foreach()-Menetelmällä

Olet jo entuudestaan perehtynyt forEach()-metodiin, sillä olet käyttänyt sitä käytännössä tulostaaksesi jokaisen kokoelman alkion konsoliin. Tarkastellaan sitä nyt tarkemmin ja tutustutaan sen toteutuksiin.

Se tarjoaa kätevän tavan käsitellä dataa funktionaalisella tyylillä. On kuitenkin tärkeää huomioida, että käsittelyjärjestys riippuu virran tyypistä ja käytetystä metodista.

Stream API:ssa on kaksi forEach()-metodin toteutusta. Käydään ne läpi yksitellen.

forEach-metodi

Suorittaa toiminnon jokaiselle alkiolle, mutta käsittelyjärjestystä ei taata rinnakkaisissa virroissa.

void forEach(Consumer<? super T> action)

Metodi forEach() ottaa argumenttina Consumer<T>-rajapinnan—funktionaalisen rajapinnan, joka määrittelee toiminnon jokaiselle virran alkiolle. Sitä käytetään yleisesti lokitukseen, tulostukseen tai sivuvaikutusten suorittamiseen.

Käytännön esimerkki

Verkkokaupassa käyttäjien tulee saada ilmoituksia henkilökohtaisista alennuksista. Koska järjestyksellä ei ole merkitystä, käytetään forEach()-metodia rinnakkaisessa virrassa nopeamman suorituksen saavuttamiseksi.

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 } }

Tämä koodi simuloi henkilökohtaisten alennussähköpostien lähettämistä asiakkaille. Koska käytössä on parallelStream(), sähköpostit lähetetään satunnaisessa järjestyksessä nopeuden parantamiseksi. forEach()-metodi soveltaa annettua toimintoa jokaiseen sähköpostiin.

forEachOrdered-metodi

Suorittaa toiminnon säilyttäen alkioiden järjestyksen, myös rinnakkaisissa streameissa.

void forEachOrdered(Consumer<? super T> action)

Kuten forEach, tämä metodi hyväksyy myös Consumer<T>-rajapinnan, mutta se varmistaa, että alkiot käsitellään samassa järjestyksessä kuin ne esiintyvät alkuperäisessä streamissa. Tämä on hyödyllistä, kun järjestyksen säilyttäminen on olennaista.

Käytännön esimerkki

Kuvittele maksujärjestelmä, jossa jokainen tapahtuma täytyy käsitellä täsmälleen siinä järjestyksessä kuin se saapuu. Jos maksut käsitellään väärässä järjestyksessä, se voi johtaa virheisiin, kuten virheellisiin saldolaskelmiin.

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); } }

Tämä koodi simuloi maksujen käsittelyjärjestelmää, jossa transaktiot täytyy käsitellä siinä järjestyksessä kuin ne saapuvat. parallelStream()-metodin käyttö parantaa suorituskykyä, mutta forEachOrdered() varmistaa, että järjestys säilyy.

Suorituskykyvertailu: forEach() vs. forEachOrdered()

Tarkastellaan, kuinka paljon nopeammin forEach() suorittaa verrattuna forEachOrdered()-metodiin käytettäessä rinnakkaisvirtoja. Tätä varten luodaan lista, jossa on 10 miljoonaa alkiota, käsitellään ne molemmilla menetelmillä laskemalla jokaisen luvun neliöjuuri ja kirjataan ylös suoritusaika.

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); } }

Metodi forEach() käsittelee alkioita ilman järjestyksen säilyttämistä, mahdollistaen virran jakaa tehtävät vapaasti käytettävissä oleville suoritinytimille. Tämä maksimoi suorituskyvyn, sillä jokainen säie voi poimia alkioita missä tahansa järjestyksessä ja käsitellä niitä rinnakkain ilman rajoituksia.

Metodi forEachOrdered() säilyttää alkuperäisen järjestyksen alkioille, mikä vaatii lisättyä synkronointia. Rinnakkaisessa virrassa alkiot jaetaan ensin osioihin käsittelyä varten, mutta niiden tulokset täytyy tämän jälkeen koota oikeaan järjestykseen ennen kuin ne välitetään käsittelymetodille.

1. Minkä funktionaalisen rajapinnan forEach-metodi hyväksyy?

2. Mitä tulostetta tämä koodi voi tuottaa?

question mark

Minkä funktionaalisen rajapinnan forEach-metodi hyväksyy?

Select the correct answer

question mark

Mitä tulostetta tämä koodi voi tuottaa?

Select the correct answer

Oliko kaikki selvää?

Miten voimme parantaa sitä?

Kiitos palautteestasi!

Osio 3. Luku 4

Kysy tekoälyä

expand

Kysy tekoälyä

ChatGPT

Kysy mitä tahansa tai kokeile jotakin ehdotetuista kysymyksistä aloittaaksesi keskustelumme

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

bookAlkioiden Käsittely Foreach()-Menetelmällä

Pyyhkäise näyttääksesi valikon

Olet jo entuudestaan perehtynyt forEach()-metodiin, sillä olet käyttänyt sitä käytännössä tulostaaksesi jokaisen kokoelman alkion konsoliin. Tarkastellaan sitä nyt tarkemmin ja tutustutaan sen toteutuksiin.

Se tarjoaa kätevän tavan käsitellä dataa funktionaalisella tyylillä. On kuitenkin tärkeää huomioida, että käsittelyjärjestys riippuu virran tyypistä ja käytetystä metodista.

Stream API:ssa on kaksi forEach()-metodin toteutusta. Käydään ne läpi yksitellen.

forEach-metodi

Suorittaa toiminnon jokaiselle alkiolle, mutta käsittelyjärjestystä ei taata rinnakkaisissa virroissa.

void forEach(Consumer<? super T> action)

Metodi forEach() ottaa argumenttina Consumer<T>-rajapinnan—funktionaalisen rajapinnan, joka määrittelee toiminnon jokaiselle virran alkiolle. Sitä käytetään yleisesti lokitukseen, tulostukseen tai sivuvaikutusten suorittamiseen.

Käytännön esimerkki

Verkkokaupassa käyttäjien tulee saada ilmoituksia henkilökohtaisista alennuksista. Koska järjestyksellä ei ole merkitystä, käytetään forEach()-metodia rinnakkaisessa virrassa nopeamman suorituksen saavuttamiseksi.

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 } }

Tämä koodi simuloi henkilökohtaisten alennussähköpostien lähettämistä asiakkaille. Koska käytössä on parallelStream(), sähköpostit lähetetään satunnaisessa järjestyksessä nopeuden parantamiseksi. forEach()-metodi soveltaa annettua toimintoa jokaiseen sähköpostiin.

forEachOrdered-metodi

Suorittaa toiminnon säilyttäen alkioiden järjestyksen, myös rinnakkaisissa streameissa.

void forEachOrdered(Consumer<? super T> action)

Kuten forEach, tämä metodi hyväksyy myös Consumer<T>-rajapinnan, mutta se varmistaa, että alkiot käsitellään samassa järjestyksessä kuin ne esiintyvät alkuperäisessä streamissa. Tämä on hyödyllistä, kun järjestyksen säilyttäminen on olennaista.

Käytännön esimerkki

Kuvittele maksujärjestelmä, jossa jokainen tapahtuma täytyy käsitellä täsmälleen siinä järjestyksessä kuin se saapuu. Jos maksut käsitellään väärässä järjestyksessä, se voi johtaa virheisiin, kuten virheellisiin saldolaskelmiin.

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); } }

Tämä koodi simuloi maksujen käsittelyjärjestelmää, jossa transaktiot täytyy käsitellä siinä järjestyksessä kuin ne saapuvat. parallelStream()-metodin käyttö parantaa suorituskykyä, mutta forEachOrdered() varmistaa, että järjestys säilyy.

Suorituskykyvertailu: forEach() vs. forEachOrdered()

Tarkastellaan, kuinka paljon nopeammin forEach() suorittaa verrattuna forEachOrdered()-metodiin käytettäessä rinnakkaisvirtoja. Tätä varten luodaan lista, jossa on 10 miljoonaa alkiota, käsitellään ne molemmilla menetelmillä laskemalla jokaisen luvun neliöjuuri ja kirjataan ylös suoritusaika.

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); } }

Metodi forEach() käsittelee alkioita ilman järjestyksen säilyttämistä, mahdollistaen virran jakaa tehtävät vapaasti käytettävissä oleville suoritinytimille. Tämä maksimoi suorituskyvyn, sillä jokainen säie voi poimia alkioita missä tahansa järjestyksessä ja käsitellä niitä rinnakkain ilman rajoituksia.

Metodi forEachOrdered() säilyttää alkuperäisen järjestyksen alkioille, mikä vaatii lisättyä synkronointia. Rinnakkaisessa virrassa alkiot jaetaan ensin osioihin käsittelyä varten, mutta niiden tulokset täytyy tämän jälkeen koota oikeaan järjestykseen ennen kuin ne välitetään käsittelymetodille.

1. Minkä funktionaalisen rajapinnan forEach-metodi hyväksyy?

2. Mitä tulostetta tämä koodi voi tuottaa?

question mark

Minkä funktionaalisen rajapinnan forEach-metodi hyväksyy?

Select the correct answer

question mark

Mitä tulostetta tämä koodi voi tuottaa?

Select the correct answer

Oliko kaikki selvää?

Miten voimme parantaa sitä?

Kiitos palautteestasi!

Osio 3. Luku 4
some-alt