Notice: This page requires JavaScript to function properly.
Please enable JavaScript in your browser settings or update your browser.
Oppiskele Suorituskyky Stream API:ssa | Stream API:n Käytännön Sovellukset
Stream API

bookSuorituskyky Stream API:ssa

Olet onnistuneesti refaktoroinut koodin, tehden siitä selkeämmän, lyhyemmän ja ilmaisullisemman. Mutta entä suorituskyky? Kuinka tehokas Stream API on verrattuna perinteisiin silmukoihin? Voiko sitä nopeuttaa käyttämällä parallelStream()-menetelmää? Otetaan siitä selvää!

Suoritusajan mittaaminen

Objektiivisen suorituskyvyn vertailun vuoksi luodaan testiaineisto, jossa on 100 000 käyttäjää ja erilaisia tilauksia. Toteutetaan kolme suodatustapaa:

  • Perinteinen for-loop – klassinen tapa sisäkkäisillä silmukoilla;
  • Stream API (stream()) – moderni deklaratiivinen menetelmä;
  • Parallel Stream API (parallelStream()) – monisäikeinen käsittely.

Suoritusajan mittaamiseen käytetään System.nanoTime(), joka tarjoaa tarkan aikavälin mittauksen.

Testin toteutus

Luodaan 100 000 käyttäjää, joilla kaikilla on yli 10 000 dollarin tilaukset, ja ajetaan kaikki kolme menetelmää nähdäksemme, mikä niistä on paras suorituskyvyltään.

Main.java

Main.java

copy
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
package com.example; import java.util.ArrayList; import java.util.List; public class Main { public static void main(String[] args) { List<User> users = generateUsers(100000); // Measuring traditional loop execution time long startTime = System.nanoTime(); List<User> premiumUsersLoop = new ArrayList<>(); for (User user : users) { if (user.isActive()) { int totalOrders = 0; for (Order order : user.getOrders()) { if (order.getTotal() >= 10000) { totalOrders++; } } if (totalOrders >= 3) { premiumUsersLoop.add(user); } } } long endTime = System.nanoTime(); System.out.println("For-loop: " + (endTime - startTime) / 1_000_000 + " ms"); // Measuring Stream API execution time startTime = System.nanoTime(); List<User> premiumUsersStream = users.stream() .filter(User::isActive) .filter(user -> user.getOrders().stream() .filter(order -> order.getTotal() >= 10000) .count() >= 3) .toList(); endTime = System.nanoTime(); System.out.println("Stream API: " + (endTime - startTime) / 1_000_000 + " ms"); // Measuring Parallel Stream API execution time startTime = System.nanoTime(); List<User> premiumUsersParallelStream = users.parallelStream() .filter(User::isActive) .filter(user -> user.getOrders().stream() .filter(order -> order.getTotal() >= 10000) .count() >= 3) .toList(); endTime = System.nanoTime(); System.out.println("Parallel Stream API: " + (endTime - startTime) / 1_000_000 + " ms"); } private static List<User> generateUsers(int count) { List<User> users = new ArrayList<>(); for (int i = 0; i < count; i++) { users.add(new User("User" + i, true, List.of( new Order(14000), new Order(5000), new Order(7000) ))); } return users; } } class Order { private final double total; public Order(double total) { this.total = total; } public double getTotal() { return total; } } class User { private final String name; private final boolean active; private final List<Order> orders; public User(String name, boolean active, List<Order> orders) { this.name = name; this.active = active; this.orders = orders; } public boolean isActive() { return active; } public List<Order> getOrders() { return orders; } @Override public String toString() { return "User{name='" + name + "'}"; } }

Suoritettaessa testiä 100 000 käyttäjällä voidaan havaita seuraavia suuntauksia:

Perinteinen for-loop on nopeampi yksinkertaisissa operaatioissa, koska se välttää streamin luonnista ja ylimääräisistä olioista aiheutuvan ylikuorman. Se toimii parhaiten, kun raaka suorituskyky on etusijalla.

Stream API on joskus hieman hitaampi ylimääräisten stream-olioiden vuoksi, mutta se parantaa merkittävästi koodin luettavuutta ja ylläpidettävyyttä.

Rinnakkaisella Stream API:lla voidaan nopeuttaa käsittelyä moniydinkoneilla, mutta ei aina. Jos aineisto on pieni, säikeiden hallinnasta aiheutuva ylikuorma voi itse asiassa hidastaa toimintaa. Se soveltuu parhaiten raskaaseen laskentaan, mutta ei silloin, kun muokataan jaettuja muuttujia, koska säikeet toimivat itsenäisesti.

Yhteenveto

Stream API on tehokas työkalu, joka tekee koodista luettavampaa ja ytimekkäämpää. Kuitenkin suorituskyvyn osalta on tärkeää ymmärtää sen rajoitukset. Joissakin tapauksissa perinteiset for-silmukat ovat nopeampia, erityisesti pienten tietoaineistojen kanssa työskenneltäessä. parallelStream() voi parantaa käsittelynopeutta, mutta sen hyöty tulee varmistaa testaamalla.

Oikean lähestymistavan valinnan tulisi olla tarkoituksellista: jos luettavuus on etusijalla, käytä Stream API:a; jos suorituskyky on kriittistä, testaa ja mittaa!

1. Mikä lähestymistapa on tyypillisesti nopein yksinkertaisissa operaatioissa?

2. Miksi Stream API voi olla hitaampi kuin tavallinen silmukka?

3. Milloin parallelStream() voi hidastaa suoritusta?

question mark

Mikä lähestymistapa on tyypillisesti nopein yksinkertaisissa operaatioissa?

Select the correct answer

question mark

Miksi Stream API voi olla hitaampi kuin tavallinen silmukka?

Select the correct answer

question mark

Milloin parallelStream() voi hidastaa suoritusta?

Select the correct answer

Oliko kaikki selvää?

Miten voimme parantaa sitä?

Kiitos palautteestasi!

Osio 4. Luku 2

Kysy tekoälyä

expand

Kysy tekoälyä

ChatGPT

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

Suggested prompts:

Can you explain when it's best to use Stream API versus traditional loops?

How does parallelStream() actually work under the hood?

What are some real-world scenarios where parallelStream() would be beneficial?

Awesome!

Completion rate improved to 2.33

bookSuorituskyky Stream API:ssa

Pyyhkäise näyttääksesi valikon

Olet onnistuneesti refaktoroinut koodin, tehden siitä selkeämmän, lyhyemmän ja ilmaisullisemman. Mutta entä suorituskyky? Kuinka tehokas Stream API on verrattuna perinteisiin silmukoihin? Voiko sitä nopeuttaa käyttämällä parallelStream()-menetelmää? Otetaan siitä selvää!

Suoritusajan mittaaminen

Objektiivisen suorituskyvyn vertailun vuoksi luodaan testiaineisto, jossa on 100 000 käyttäjää ja erilaisia tilauksia. Toteutetaan kolme suodatustapaa:

  • Perinteinen for-loop – klassinen tapa sisäkkäisillä silmukoilla;
  • Stream API (stream()) – moderni deklaratiivinen menetelmä;
  • Parallel Stream API (parallelStream()) – monisäikeinen käsittely.

Suoritusajan mittaamiseen käytetään System.nanoTime(), joka tarjoaa tarkan aikavälin mittauksen.

Testin toteutus

Luodaan 100 000 käyttäjää, joilla kaikilla on yli 10 000 dollarin tilaukset, ja ajetaan kaikki kolme menetelmää nähdäksemme, mikä niistä on paras suorituskyvyltään.

Main.java

Main.java

copy
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
package com.example; import java.util.ArrayList; import java.util.List; public class Main { public static void main(String[] args) { List<User> users = generateUsers(100000); // Measuring traditional loop execution time long startTime = System.nanoTime(); List<User> premiumUsersLoop = new ArrayList<>(); for (User user : users) { if (user.isActive()) { int totalOrders = 0; for (Order order : user.getOrders()) { if (order.getTotal() >= 10000) { totalOrders++; } } if (totalOrders >= 3) { premiumUsersLoop.add(user); } } } long endTime = System.nanoTime(); System.out.println("For-loop: " + (endTime - startTime) / 1_000_000 + " ms"); // Measuring Stream API execution time startTime = System.nanoTime(); List<User> premiumUsersStream = users.stream() .filter(User::isActive) .filter(user -> user.getOrders().stream() .filter(order -> order.getTotal() >= 10000) .count() >= 3) .toList(); endTime = System.nanoTime(); System.out.println("Stream API: " + (endTime - startTime) / 1_000_000 + " ms"); // Measuring Parallel Stream API execution time startTime = System.nanoTime(); List<User> premiumUsersParallelStream = users.parallelStream() .filter(User::isActive) .filter(user -> user.getOrders().stream() .filter(order -> order.getTotal() >= 10000) .count() >= 3) .toList(); endTime = System.nanoTime(); System.out.println("Parallel Stream API: " + (endTime - startTime) / 1_000_000 + " ms"); } private static List<User> generateUsers(int count) { List<User> users = new ArrayList<>(); for (int i = 0; i < count; i++) { users.add(new User("User" + i, true, List.of( new Order(14000), new Order(5000), new Order(7000) ))); } return users; } } class Order { private final double total; public Order(double total) { this.total = total; } public double getTotal() { return total; } } class User { private final String name; private final boolean active; private final List<Order> orders; public User(String name, boolean active, List<Order> orders) { this.name = name; this.active = active; this.orders = orders; } public boolean isActive() { return active; } public List<Order> getOrders() { return orders; } @Override public String toString() { return "User{name='" + name + "'}"; } }

Suoritettaessa testiä 100 000 käyttäjällä voidaan havaita seuraavia suuntauksia:

Perinteinen for-loop on nopeampi yksinkertaisissa operaatioissa, koska se välttää streamin luonnista ja ylimääräisistä olioista aiheutuvan ylikuorman. Se toimii parhaiten, kun raaka suorituskyky on etusijalla.

Stream API on joskus hieman hitaampi ylimääräisten stream-olioiden vuoksi, mutta se parantaa merkittävästi koodin luettavuutta ja ylläpidettävyyttä.

Rinnakkaisella Stream API:lla voidaan nopeuttaa käsittelyä moniydinkoneilla, mutta ei aina. Jos aineisto on pieni, säikeiden hallinnasta aiheutuva ylikuorma voi itse asiassa hidastaa toimintaa. Se soveltuu parhaiten raskaaseen laskentaan, mutta ei silloin, kun muokataan jaettuja muuttujia, koska säikeet toimivat itsenäisesti.

Yhteenveto

Stream API on tehokas työkalu, joka tekee koodista luettavampaa ja ytimekkäämpää. Kuitenkin suorituskyvyn osalta on tärkeää ymmärtää sen rajoitukset. Joissakin tapauksissa perinteiset for-silmukat ovat nopeampia, erityisesti pienten tietoaineistojen kanssa työskenneltäessä. parallelStream() voi parantaa käsittelynopeutta, mutta sen hyöty tulee varmistaa testaamalla.

Oikean lähestymistavan valinnan tulisi olla tarkoituksellista: jos luettavuus on etusijalla, käytä Stream API:a; jos suorituskyky on kriittistä, testaa ja mittaa!

1. Mikä lähestymistapa on tyypillisesti nopein yksinkertaisissa operaatioissa?

2. Miksi Stream API voi olla hitaampi kuin tavallinen silmukka?

3. Milloin parallelStream() voi hidastaa suoritusta?

question mark

Mikä lähestymistapa on tyypillisesti nopein yksinkertaisissa operaatioissa?

Select the correct answer

question mark

Miksi Stream API voi olla hitaampi kuin tavallinen silmukka?

Select the correct answer

question mark

Milloin parallelStream() voi hidastaa suoritusta?

Select the correct answer

Oliko kaikki selvää?

Miten voimme parantaa sitä?

Kiitos palautteestasi!

Osio 4. Luku 2
some-alt