Arreglos

La clase Stream en Java

Descubre la clase Stream en Java, una herramienta poderosa para procesar colecciones de datos de manera eficiente y funcional. Aprende a utilizar Stream para realizar operaciones como filtrado, mapeo, reducción y más, facilitando el manejo de datos en tus aplicaciones Java.

¿Qué es la clase Stream?

La clase Stream en Java es una herramienta poderosa para procesar colecciones de datos de manera eficiente y funcional. Introducida en Java 8, la clase Stream forma parte del paquete java.util.stream y proporciona una forma de realizar operaciones como filtrado, mapeo, reducción y más, facilitando el manejo de datos en tus aplicaciones Java.

Operaciones comunes con Stream

Filtrado

El método filter() se utiliza para filtrar elementos de un stream según una condición específica. Por ejemplo, si queremos filtrar una lista de números para obtener solo los números pares, podemos hacer lo siguiente:

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class Main {
    void main() {
        List<Integer> numeros = Arrays.asList(1, 2, 3, 4, 5, 6);
        List<Integer> numerosPares = numeros.stream()
                                            .filter(n -> n % 2 == 0)
                                            .collect(Collectors.toList());
        System.out.println(numerosPares); // Output: [2, 4, 6]
    }
}
Ten en cuenta que para recoger los resultados de un stream en una colección, como una lista, es necesario utilizar el método collect() junto con un colector adecuado, como Collectors.toList() que nos permite obtener una lista con los elementos filtrados. Si no utilizamos collect(), el stream no se ejecutará y no obtendremos ningún resultado, ya que las operaciones en un stream son perezosas (lazy) y solo se ejecutan cuando es necesario.

Los tipos de "colectores" disponibles en Java son:

ColectorDescripción
Collectors.toList()Recoge los elementos del stream en una lista.
Collectors.toSet()Recoge los elementos del stream en un conjunto (set), eliminando duplicados.
Collectors.toMap()Recoge los elementos del stream en un mapa (map), donde se especifican las claves y los valores.
Collectors.joining()Recoge los elementos del stream en una cadena de texto, concatenándolos con un separador opcional.
Collectors.groupingBy()Agrupa los elementos del stream según una función de clasificación, creando un mapa donde las claves son los resultados de la función y los valores son listas de elementos que corresponden a cada clave.
Collectors.partitioningBy()Particiona los elementos del stream en dos grupos según una condición, creando un mapa donde las claves son true y false, y los valores son listas de elementos que corresponden a cada grupo.
Collectors.counting()Cuenta el número de elementos en el stream.
Collectors.summarizingInt(), Collectors.summarizingDouble(), Collectors.summarizingLong()Recoge estadísticas como el conteo, la suma, el mínimo, el promedio y el máximo de los elementos del stream, según el tipo de datos.
Collectors.reducing()Realiza una reducción de los elementos del stream utilizando una función de acumulación, como suma, multiplicación, etc.

Para consultar la documentación oficial de Java sobre los colectores, puedes visitar el siguiente enlace: Java Collectors Documentation.

Mapeo

El método map() se utiliza para transformar los elementos de un stream aplicando una función a cada elemento. Por ejemplo, si queremos convertir una lista de cadenas de texto a mayúsculas, podemos hacer lo siguiente:

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class Main {
    void main() {
        List<String> palabras = Arrays.asList("hola", "mundo", "java");
        List<String> palabrasMayusculas = palabras.stream()
                                                  .map(String::toUpperCase)
                                                  .collect(Collectors.toList());
        System.out.println(palabrasMayusculas); // Output: [HOLA, MUNDO, JAVA]
    }
}
Recuerda que el método map() no modifica la colección original, sino que devuelve un nuevo stream con los elementos transformados. Por lo tanto, es importante recoger los resultados en una nueva colección utilizando collect() para obtener los elementos transformados. Si no utilizamos collect(), el stream no se ejecutará y no obtendremos ningún resultado, ya que las operaciones en un stream son perezosas (lazy) y solo se ejecutan cuando es necesario. Además, ten en cuenta que el método map() puede ser utilizado para realizar cualquier tipo de transformación, no solo para convertir a mayúsculas. Puedes aplicar cualquier función que desees a los elementos del stream, como convertir a minúsculas, extraer una parte de la cadena, incluso funciones más complejas como calcular la longitud de las cadenas, etc. La flexibilidad del método map() te permite realizar una amplia variedad de transformaciones en tus datos de manera eficiente y concisa. Incluyendo las funciones lambda, que son una forma de escribir funciones anónimas de manera más concisa. Por ejemplo, en lugar de escribir map(String::toUpperCase), podríamos escribir map(s -> s.toUpperCase()), lo que hace exactamente lo mismo pero utilizando una expresión lambda. Las expresiones lambda son especialmente útiles cuando queremos realizar transformaciones más complejas o cuando no queremos crear métodos adicionales para nuestras transformaciones. En resumen, el método map() es una herramienta poderosa para transformar los elementos de un stream de manera eficiente y concisa, permitiéndonos aplicar cualquier función que deseemos a nuestros datos.

Reducción

El método reduce() se utiliza para combinar los elementos de un stream en un solo resultado utilizando una función de acumulación. Por ejemplo, si queremos sumar una lista de números, podemos hacer lo siguiente:

import java.util.Arrays;
import java.util.List;
import java.util.Optional;

public class Main {
    void main() {
        List<Integer> numeros = Arrays.asList(1, 2, 3, 4, 5);
        Optional<Integer> suma = numeros.stream()
                                        .reduce((a, b) -> a + b);
        suma.ifPresent(System.out::println); // Output: 15
    }
}
Ten en cuenta que el método reduce() devuelve un Optional porque el resultado de la reducción puede no estar presente si el stream está vacío. Por lo tanto, es importante manejar el caso en el que el stream no tenga elementos para evitar errores. Puedes utilizar el método ifPresent() para ejecutar una acción solo si el resultado de la reducción está presente, o puedes proporcionar un valor predeterminado utilizando el método orElse() en caso de que el stream esté vacío. Por ejemplo:
Integer suma = numeros.stream()
                     .reduce(0, (a, b) -> a + b);
System.out.println(suma); // Output: 15
En este caso, hemos proporcionado un valor predeterminado de 0 para la reducción, lo que significa que si el stream está vacío, el resultado será 0 en lugar de un Optional vacío. Esto puede ser útil en situaciones donde deseas asegurarte de obtener un resultado incluso cuando no hay elementos en el stream. En resumen, el método reduce() es una herramienta poderosa para combinar los elementos de un stream en un solo resultado utilizando una función de acumulación, pero es importante manejar adecuadamente el caso en el que el stream esté vacío para evitar errores y obtener resultados consistentes.

Conclusión

En resumen, la clase Stream en Java es una herramienta poderosa para procesar colecciones de datos de manera eficiente y funcional. Con métodos como filter(), map() y reduce(), puedes realizar operaciones complejas en tus datos de manera concisa y legible. Además, los colectores disponibles en Java te permiten recoger los resultados de tus operaciones en diferentes tipos de colecciones, facilitando aún más el manejo de tus datos. Al utilizar la clase Stream, puedes escribir código más limpio, eficiente y fácil de mantener para procesar tus datos en Java.

Copyright Jesús Aurelio Castro Magaña © 2026