Notice: This page requires JavaScript to function properly.
Please enable JavaScript in your browser settings or update your browser.
Impara Prestazioni Nello Stream API | Applicazioni Pratiche Dello Stream API
Stream API

bookPrestazioni Nello Stream API

Hai refattorizzato con successo il codice, rendendolo più pulito, più breve e più espressivo. Ma che dire delle prestazioni? Quanto è efficiente lo Stream API rispetto ai cicli tradizionali? È possibile aumentare la velocità utilizzando parallelStream()? Scopriamolo!

Misurazione del tempo di esecuzione

Per confrontare oggettivamente le prestazioni, verrà creato un dataset di test con 100.000 utenti e diversi ordini. Successivamente, verranno implementati tre approcci di filtraggio:

  • for-loop tradizionale – approccio classico con cicli annidati;
  • Stream API (stream()) – metodo dichiarativo moderno;
  • Parallel Stream API (parallelStream()) – elaborazione multithread.

Il tempo di esecuzione verrà misurato utilizzando System.nanoTime(), che fornisce differenze temporali ad alta precisione.

Implementazione del test

Verranno generati 100.000 utenti, assicurando che tutti abbiano ordini superiori a $10.000, ed eseguiti tutti e tre gli approcci per verificare quale risulta il più performante.

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 + "'}"; } }

Dopo aver eseguito il test con 100.000 utenti, è possibile osservare le seguenti tendenze:

Il tradizionale for-loop risulta più veloce per operazioni semplici poiché evita l'overhead dovuto alla creazione dello stream e di oggetti aggiuntivi. Offre le migliori prestazioni quando la velocità pura è una priorità.

La Stream API risulta talvolta leggermente più lenta a causa degli oggetti stream aggiuntivi, ma migliora notevolmente la leggibilità e la manutenibilità del codice.

La Parallel Stream API può velocizzare l'elaborazione su sistemi multi-core, ma non sempre. Se il dataset è piccolo, l'overhead della gestione dei thread può effettivamente rallentare l'esecuzione. È più efficace per calcoli complessi, ma non quando si modificano variabili condivise, poiché i thread vengono eseguiti in modo indipendente.

Riepilogo

Stream API è uno strumento potente che rende il codice più leggibile e conciso. Tuttavia, per quanto riguarda le prestazioni, è importante comprenderne i limiti. In alcuni casi, i tradizionali for-loop sono più veloci, soprattutto quando si lavora con piccoli dataset. parallelStream() può migliorare la velocità di elaborazione, ma richiede test per assicurarsi che offra realmente un vantaggio.

Quindi, la scelta dell'approccio giusto deve essere intenzionale: se la leggibilità è una priorità, utilizzare Stream API; se le prestazioni sono fondamentali, testare e misurare!

1. Quale approccio è tipicamente il più veloce per operazioni semplici?

2. Perché Stream API può essere più lento di un ciclo regolare?

3. Quando può parallelStream() rallentare l'esecuzione?

question mark

Quale approccio è tipicamente il più veloce per operazioni semplici?

Select the correct answer

question mark

Perché Stream API può essere più lento di un ciclo regolare?

Select the correct answer

question mark

Quando può parallelStream() rallentare l'esecuzione?

Select the correct answer

Tutto è chiaro?

Come possiamo migliorarlo?

Grazie per i tuoi commenti!

Sezione 4. Capitolo 2

Chieda ad AI

expand

Chieda ad AI

ChatGPT

Chieda pure quello che desidera o provi una delle domande suggerite per iniziare la nostra conversazione

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

bookPrestazioni Nello Stream API

Scorri per mostrare il menu

Hai refattorizzato con successo il codice, rendendolo più pulito, più breve e più espressivo. Ma che dire delle prestazioni? Quanto è efficiente lo Stream API rispetto ai cicli tradizionali? È possibile aumentare la velocità utilizzando parallelStream()? Scopriamolo!

Misurazione del tempo di esecuzione

Per confrontare oggettivamente le prestazioni, verrà creato un dataset di test con 100.000 utenti e diversi ordini. Successivamente, verranno implementati tre approcci di filtraggio:

  • for-loop tradizionale – approccio classico con cicli annidati;
  • Stream API (stream()) – metodo dichiarativo moderno;
  • Parallel Stream API (parallelStream()) – elaborazione multithread.

Il tempo di esecuzione verrà misurato utilizzando System.nanoTime(), che fornisce differenze temporali ad alta precisione.

Implementazione del test

Verranno generati 100.000 utenti, assicurando che tutti abbiano ordini superiori a $10.000, ed eseguiti tutti e tre gli approcci per verificare quale risulta il più performante.

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 + "'}"; } }

Dopo aver eseguito il test con 100.000 utenti, è possibile osservare le seguenti tendenze:

Il tradizionale for-loop risulta più veloce per operazioni semplici poiché evita l'overhead dovuto alla creazione dello stream e di oggetti aggiuntivi. Offre le migliori prestazioni quando la velocità pura è una priorità.

La Stream API risulta talvolta leggermente più lenta a causa degli oggetti stream aggiuntivi, ma migliora notevolmente la leggibilità e la manutenibilità del codice.

La Parallel Stream API può velocizzare l'elaborazione su sistemi multi-core, ma non sempre. Se il dataset è piccolo, l'overhead della gestione dei thread può effettivamente rallentare l'esecuzione. È più efficace per calcoli complessi, ma non quando si modificano variabili condivise, poiché i thread vengono eseguiti in modo indipendente.

Riepilogo

Stream API è uno strumento potente che rende il codice più leggibile e conciso. Tuttavia, per quanto riguarda le prestazioni, è importante comprenderne i limiti. In alcuni casi, i tradizionali for-loop sono più veloci, soprattutto quando si lavora con piccoli dataset. parallelStream() può migliorare la velocità di elaborazione, ma richiede test per assicurarsi che offra realmente un vantaggio.

Quindi, la scelta dell'approccio giusto deve essere intenzionale: se la leggibilità è una priorità, utilizzare Stream API; se le prestazioni sono fondamentali, testare e misurare!

1. Quale approccio è tipicamente il più veloce per operazioni semplici?

2. Perché Stream API può essere più lento di un ciclo regolare?

3. Quando può parallelStream() rallentare l'esecuzione?

question mark

Quale approccio è tipicamente il più veloce per operazioni semplici?

Select the correct answer

question mark

Perché Stream API può essere più lento di un ciclo regolare?

Select the correct answer

question mark

Quando può parallelStream() rallentare l'esecuzione?

Select the correct answer

Tutto è chiaro?

Come possiamo migliorarlo?

Grazie per i tuoi commenti!

Sezione 4. Capitolo 2
some-alt