Notice: This page requires JavaScript to function properly.
Please enable JavaScript in your browser settings or update your browser.
Aprende Procesamiento de Elementos con el Método forEach() | Operaciones Terminales en la Stream API
Stream API

bookProcesamiento de Elementos con el Método forEach()

Ya estás familiarizado con el método forEach() ya que lo has utilizado en la práctica para imprimir cada elemento de una colección en la consola. Analicémoslo más de cerca y exploremos sus implementaciones.

Ofrece una forma conveniente de procesar datos en un estilo funcional. Sin embargo, es importante tener en cuenta que el orden de procesamiento depende del tipo de stream y del método utilizado.

Existen dos implementaciones del método forEach() en la Stream API. Revisémoslas una por una.

Método forEach

Ejecuta una acción en cada elemento, pero el orden de procesamiento no está garantizado en streams paralelos.

void forEach(Consumer<? super T> action)

El método forEach() recibe un Consumer<T> como argumento—una interfaz funcional que define una operación para cada elemento en el stream. Se utiliza comúnmente para registro, impresión o para realizar efectos secundarios.

Ejemplo práctico

En una tienda en línea, los usuarios necesitan recibir notificaciones sobre descuentos personalizados. Como el orden no es relevante, se utiliza forEach() con un stream paralelo para una ejecución más rápida.

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

Este código simula el envío de correos electrónicos de descuento personalizados a clientes. Dado que se utiliza parallelStream(), los correos se envían en ningún orden específico para mejorar la velocidad. El método forEach() aplica la acción dada a cada correo electrónico.

Método forEachOrdered

Ejecuta una acción preservando el orden de los elementos, incluso en streams paralelos.

void forEachOrdered(Consumer<? super T> action)

Al igual que forEach, este método también acepta un Consumer<T>, pero garantiza que los elementos se procesen en el mismo orden en que aparecen en el stream original. Esto resulta útil cuando es fundamental mantener la secuencia.

Ejemplo práctico

Imagínese un sistema de pagos donde cada transacción debe procesarse en el orden exacto en que llega. Si los pagos se gestionan fuera de secuencia, pueden producirse errores, como cálculos incorrectos de saldos.

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

Este código simula un sistema de procesamiento de pagos donde las transacciones deben gestionarse en el orden en que llegan. El uso de parallelStream() mejora el rendimiento, pero forEachOrdered() garantiza que la secuencia se mantenga intacta.

Comparación de rendimiento: forEach() vs. forEachOrdered()

Se mide cuán rápido se ejecuta forEach() en comparación con forEachOrdered() al trabajar con streams paralelos. Para ello, se crea una lista de 10 millones de elementos, se procesan utilizando ambos métodos calculando la raíz cuadrada de cada número y se registra el tiempo de ejecución.

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

El método forEach() procesa elementos sin preservar el orden, permitiendo que el stream distribuya libremente las tareas entre los núcleos del procesador disponibles. Esto maximiza el rendimiento, ya que cada hilo puede tomar elementos en cualquier orden y procesarlos en paralelo sin restricciones.

El método forEachOrdered() preserva el orden original de los elementos, lo que requiere sincronización adicional. En un stream paralelo, los elementos se dividen primero en fragmentos para su procesamiento, pero sus resultados deben ser reensamblados en el orden correcto antes de ser pasados al método de procesamiento.

1. ¿Qué interfaz funcional acepta el método forEach?

2. ¿Qué salida puede producir este código?

question mark

¿Qué interfaz funcional acepta el método forEach?

Select the correct answer

question mark

¿Qué salida puede producir este código?

Select the correct answer

¿Todo estuvo claro?

¿Cómo podemos mejorarlo?

¡Gracias por tus comentarios!

Sección 3. Capítulo 4

Pregunte a AI

expand

Pregunte a AI

ChatGPT

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

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

bookProcesamiento de Elementos con el Método forEach()

Desliza para mostrar el menú

Ya estás familiarizado con el método forEach() ya que lo has utilizado en la práctica para imprimir cada elemento de una colección en la consola. Analicémoslo más de cerca y exploremos sus implementaciones.

Ofrece una forma conveniente de procesar datos en un estilo funcional. Sin embargo, es importante tener en cuenta que el orden de procesamiento depende del tipo de stream y del método utilizado.

Existen dos implementaciones del método forEach() en la Stream API. Revisémoslas una por una.

Método forEach

Ejecuta una acción en cada elemento, pero el orden de procesamiento no está garantizado en streams paralelos.

void forEach(Consumer<? super T> action)

El método forEach() recibe un Consumer<T> como argumento—una interfaz funcional que define una operación para cada elemento en el stream. Se utiliza comúnmente para registro, impresión o para realizar efectos secundarios.

Ejemplo práctico

En una tienda en línea, los usuarios necesitan recibir notificaciones sobre descuentos personalizados. Como el orden no es relevante, se utiliza forEach() con un stream paralelo para una ejecución más rápida.

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

Este código simula el envío de correos electrónicos de descuento personalizados a clientes. Dado que se utiliza parallelStream(), los correos se envían en ningún orden específico para mejorar la velocidad. El método forEach() aplica la acción dada a cada correo electrónico.

Método forEachOrdered

Ejecuta una acción preservando el orden de los elementos, incluso en streams paralelos.

void forEachOrdered(Consumer<? super T> action)

Al igual que forEach, este método también acepta un Consumer<T>, pero garantiza que los elementos se procesen en el mismo orden en que aparecen en el stream original. Esto resulta útil cuando es fundamental mantener la secuencia.

Ejemplo práctico

Imagínese un sistema de pagos donde cada transacción debe procesarse en el orden exacto en que llega. Si los pagos se gestionan fuera de secuencia, pueden producirse errores, como cálculos incorrectos de saldos.

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

Este código simula un sistema de procesamiento de pagos donde las transacciones deben gestionarse en el orden en que llegan. El uso de parallelStream() mejora el rendimiento, pero forEachOrdered() garantiza que la secuencia se mantenga intacta.

Comparación de rendimiento: forEach() vs. forEachOrdered()

Se mide cuán rápido se ejecuta forEach() en comparación con forEachOrdered() al trabajar con streams paralelos. Para ello, se crea una lista de 10 millones de elementos, se procesan utilizando ambos métodos calculando la raíz cuadrada de cada número y se registra el tiempo de ejecución.

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

El método forEach() procesa elementos sin preservar el orden, permitiendo que el stream distribuya libremente las tareas entre los núcleos del procesador disponibles. Esto maximiza el rendimiento, ya que cada hilo puede tomar elementos en cualquier orden y procesarlos en paralelo sin restricciones.

El método forEachOrdered() preserva el orden original de los elementos, lo que requiere sincronización adicional. En un stream paralelo, los elementos se dividen primero en fragmentos para su procesamiento, pero sus resultados deben ser reensamblados en el orden correcto antes de ser pasados al método de procesamiento.

1. ¿Qué interfaz funcional acepta el método forEach?

2. ¿Qué salida puede producir este código?

question mark

¿Qué interfaz funcional acepta el método forEach?

Select the correct answer

question mark

¿Qué salida puede producir este código?

Select the correct answer

¿Todo estuvo claro?

¿Cómo podemos mejorarlo?

¡Gracias por tus comentarios!

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