Transforma tus bucles anidados en Streams de Java: Guía Práctica y Moderna

Carlos ExpositoCarlos Exposito
3 min read

Transforma tus bucles anidados en Streams de Java: Guía Práctica y Moderna

La API de Streams, introducida en Java 8, revolucionó la forma en que procesamos datos. Gracias a ella, podemos escribir código más limpio, declarativo y eficiente. En este artículo aprenderás a transformar bucles anidados en Streams, con ejemplos paso a paso que te harán amar la programación funcional en Java. 💡

🚀 1. ¿Qué es un Stream en Java?

Un Stream es una secuencia de elementos que se procesan de forma funcional y perezosa desde una fuente (colección, array o archivo). A diferencia de las colecciones, los Streams no almacenan datos, sino que los transforman.

Las operaciones en Streams se dividen en:

  • Intermedias: como map(), filter() y flatMap().
  • Terminales: como collect(), forEach(), findFirst().

Por ejemplo, flatMap() es ideal para trabajar con estructuras anidadas, como listas de listas, y transformarlas en un único flujo plano.


🔁 2. Iteración Básica: Pares de dos listas

Versión con bucles:

public static List<int[]> obtenerParesImperativo(List<Integer> lista1, List<Integer> lista2) {
    List<int[]> pares = new ArrayList<>();
    for (Integer a : lista1) {
        for (Integer b : lista2) {
            pares.add(new int[]{a, b});
        }
    }
    return pares;
}

Versión con Streams:

public static List<int[]> obtenerParesStream(List<Integer> lista1, List<Integer> lista2) {
    return lista1.stream()
        .flatMap(a -> lista2.stream().map(b -> new int[]{a, b}))
        .collect(Collectors.toList());
}

Este enfoque es más limpio y expresivo, especialmente en operaciones complejas.


🎯 3. Añadiendo Condiciones: Filtrar resultados

Bucles con condición:

public static List<int[]> filtrarParesImperativo(List<Integer> lista1, List<Integer> lista2) {
    List<int[]> pares = new ArrayList<>();
    for (Integer a : lista1) {
        for (Integer b : lista2) {
            if (a + b > 7) {
                pares.add(new int[]{a, b});
            }
        }
    }
    return pares;
}

Streams con filter():

public static List<int[]> filtrarParesStream(List<Integer> lista1, List<Integer> lista2) {
    return lista1.stream()
        .flatMap(a -> lista2.stream().map(b -> new int[]{a, b}))
        .filter(par -> par[0] + par[1] > 7)
        .collect(Collectors.toList());
}

Separamos la lógica de iteración y filtrado, haciendo el código más modular y fácil de leer.


⛔ 4. Interrupción Temprana: Encontrar el primer resultado

Con bucles y break:

public static Optional<int[]> primerParValidoImperativo(List<Integer> lista1, List<Integer> lista2) {
    for (Integer a : lista1) {
        for (Integer b : lista2) {
            if (a + b > 7) {
                return Optional.of(new int[]{a, b});
            }
        }
    }
    return Optional.empty();
}

Con findFirst():

public static Optional<int[]> primerParValidoStream(List<Integer> lista1, List<Integer> lista2) {
    return lista1.stream()
        .flatMap(a -> lista2.stream().map(b -> new int[]{a, b}))
        .filter(par -> par[0] + par[1] > 7)
        .findFirst();
}

Gracias a findFirst(), obtenemos una funcionalidad similar al break, pero de forma más elegante y declarativa.


🧠 5. ¿Cuándo usar Streams?

✅ Úsalos cuando:

  • Quieras mejorar la legibilidad del código.
  • Necesites transformar y filtrar datos fácilmente.
  • Busques procesamiento paralelo con parallelStream().

❌ Evítalos si:

  • La operación es extremadamente sencilla.
  • El rendimiento es crítico y cada milisegundo cuenta.
  • Necesitas depuración detallada paso a paso.

🎉 Conclusión

Transformar bucles anidados en Streams no solo hace tu código más limpio, sino también más mantenible y expresivo. Si bien no todos los casos ameritan usar Streams, en muchos escenarios pueden mejorar la calidad y claridad del desarrollo.

¡Anímate a refactorizar ese código viejo y dale un aire funcional a tus proyectos en Java! 💪🚀

0
Subscribe to my newsletter

Read articles from Carlos Exposito directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Carlos Exposito
Carlos Exposito