Notice: This page requires JavaScript to function properly.
Please enable JavaScript in your browser settings or update your browser.
Aprende Rendimiento en Stream API | Aplicaciones Prácticas de Stream API
Stream API

bookRendimiento en Stream API

Has refactorizado el código con éxito, haciéndolo más limpio, más corto y más expresivo. Pero, ¿qué ocurre con el rendimiento? ¿Qué tan eficiente es Stream API en comparación con los bucles tradicionales? ¿Se puede acelerar utilizando parallelStream()? ¡Vamos a descubrirlo!

Medición del tiempo de ejecución

Para comparar objetivamente el rendimiento, se creará un conjunto de datos de prueba con 100,000 usuarios y diferentes órdenes. Luego, se implementarán tres enfoques de filtrado:

  • for-loop tradicional – un enfoque clásico con bucles anidados;
  • Stream API (stream()) – un método declarativo moderno;
  • Parallel Stream API (parallelStream()) – procesamiento multihilo.

Se medirá el tiempo de ejecución utilizando System.nanoTime(), que proporciona diferencias de tiempo de alta precisión.

Implementación de la prueba

Se generarán 100,000 usuarios, asegurando que todos tengan órdenes superiores a $10,000, y se ejecutarán los tres enfoques para ver cuál ofrece el mejor rendimiento.

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

Después de ejecutar la prueba con 100,000 usuarios, se pueden observar las siguientes tendencias:

El for-loop tradicional es más rápido para operaciones simples ya que evita la sobrecarga de la creación de streams y objetos adicionales. Ofrece el mejor rendimiento cuando la velocidad bruta es prioritaria.

La Stream API a veces es ligeramente más lenta debido a los objetos de stream adicionales, pero mejora significativamente la legibilidad y mantenibilidad del código.

La Parallel Stream API puede acelerar el procesamiento en sistemas multinúcleo, pero no siempre. Si el conjunto de datos es pequeño, la sobrecarga de la gestión de hilos puede incluso ralentizarla. Funciona mejor para cálculos pesados, pero no cuando se modifican variables compartidas, ya que los hilos se ejecutan de forma independiente.

Resumen

Stream API es una herramienta potente que hace el código más legible y conciso. Sin embargo, en cuanto al rendimiento, es importante comprender sus limitaciones. En algunos casos, los bucles for tradicionales son más rápidos, especialmente al trabajar con conjuntos de datos pequeños. parallelStream() puede mejorar la velocidad de procesamiento, pero requiere pruebas para asegurar que realmente proporciona un beneficio.

Por lo tanto, la elección del enfoque adecuado debe ser intencional: si la legibilidad es una prioridad, utilice Stream API; si el rendimiento es crítico, pruebe y mida.

1. ¿Qué enfoque suele ser el más rápido para operaciones simples?

2. ¿Por qué Stream API puede ser más lento que un bucle regular?

3. ¿Cuándo puede parallelStream() ralentizar la ejecución?

question mark

¿Qué enfoque suele ser el más rápido para operaciones simples?

Select the correct answer

question mark

¿Por qué Stream API puede ser más lento que un bucle regular?

Select the correct answer

question mark

¿Cuándo puede parallelStream() ralentizar la ejecución?

Select the correct answer

¿Todo estuvo claro?

¿Cómo podemos mejorarlo?

¡Gracias por tus comentarios!

Sección 4. Capítulo 2

Pregunte a AI

expand

Pregunte a AI

ChatGPT

Pregunte lo que quiera o pruebe una de las preguntas sugeridas para comenzar nuestra charla

Awesome!

Completion rate improved to 2.33

bookRendimiento en Stream API

Desliza para mostrar el menú

Has refactorizado el código con éxito, haciéndolo más limpio, más corto y más expresivo. Pero, ¿qué ocurre con el rendimiento? ¿Qué tan eficiente es Stream API en comparación con los bucles tradicionales? ¿Se puede acelerar utilizando parallelStream()? ¡Vamos a descubrirlo!

Medición del tiempo de ejecución

Para comparar objetivamente el rendimiento, se creará un conjunto de datos de prueba con 100,000 usuarios y diferentes órdenes. Luego, se implementarán tres enfoques de filtrado:

  • for-loop tradicional – un enfoque clásico con bucles anidados;
  • Stream API (stream()) – un método declarativo moderno;
  • Parallel Stream API (parallelStream()) – procesamiento multihilo.

Se medirá el tiempo de ejecución utilizando System.nanoTime(), que proporciona diferencias de tiempo de alta precisión.

Implementación de la prueba

Se generarán 100,000 usuarios, asegurando que todos tengan órdenes superiores a $10,000, y se ejecutarán los tres enfoques para ver cuál ofrece el mejor rendimiento.

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

Después de ejecutar la prueba con 100,000 usuarios, se pueden observar las siguientes tendencias:

El for-loop tradicional es más rápido para operaciones simples ya que evita la sobrecarga de la creación de streams y objetos adicionales. Ofrece el mejor rendimiento cuando la velocidad bruta es prioritaria.

La Stream API a veces es ligeramente más lenta debido a los objetos de stream adicionales, pero mejora significativamente la legibilidad y mantenibilidad del código.

La Parallel Stream API puede acelerar el procesamiento en sistemas multinúcleo, pero no siempre. Si el conjunto de datos es pequeño, la sobrecarga de la gestión de hilos puede incluso ralentizarla. Funciona mejor para cálculos pesados, pero no cuando se modifican variables compartidas, ya que los hilos se ejecutan de forma independiente.

Resumen

Stream API es una herramienta potente que hace el código más legible y conciso. Sin embargo, en cuanto al rendimiento, es importante comprender sus limitaciones. En algunos casos, los bucles for tradicionales son más rápidos, especialmente al trabajar con conjuntos de datos pequeños. parallelStream() puede mejorar la velocidad de procesamiento, pero requiere pruebas para asegurar que realmente proporciona un beneficio.

Por lo tanto, la elección del enfoque adecuado debe ser intencional: si la legibilidad es una prioridad, utilice Stream API; si el rendimiento es crítico, pruebe y mida.

1. ¿Qué enfoque suele ser el más rápido para operaciones simples?

2. ¿Por qué Stream API puede ser más lento que un bucle regular?

3. ¿Cuándo puede parallelStream() ralentizar la ejecución?

question mark

¿Qué enfoque suele ser el más rápido para operaciones simples?

Select the correct answer

question mark

¿Por qué Stream API puede ser más lento que un bucle regular?

Select the correct answer

question mark

¿Cuándo puede parallelStream() ralentizar la ejecución?

Select the correct answer

¿Todo estuvo claro?

¿Cómo podemos mejorarlo?

¡Gracias por tus comentarios!

Sección 4. Capítulo 2
some-alt