JavaRush /Blog Java /Random-ES /Deshacerse de los bucles en Java 8
KapChook
Nivel 19
Volga

Deshacerse de los bucles en Java 8

Publicado en el grupo Random-ES
El estilo funcional introducido en Java 8 es una gran adición al lenguaje. Ahora Java no es pura programación orientada a objetos, ahora es un híbrido de programación orientada a objetos y programación funcional. Esto cambia las reglas del juego y necesitamos cambiar nuestros cerebros OOP para absorber estos cambios. Deshacerse de los bucles en Java 8 - 1Pero ¿por qué deberíamos aceptar estos cambios? ¿Por qué deberíamos perder el tiempo intentando llevarnos bien con un estilo funcional cuando podemos resolver el problema utilizando programación orientada a objetos pura?
  • El estilo funcional introducido en Java 8 nos ayuda a reducir la brecha entre la lógica empresarial y el código. Nos permite contar la historia de forma natural a un nivel superior. En lugar de decir cómo quieres hacerlo, puedes decir lo que quieres hacer.

  • El código se vuelve más limpio y conciso.

  • Las funciones de alto orden nos permiten:

    • Enviar funciones a otras funciones
    • Crear funciones dentro de otras funciones.
    • Funciones de retorno de otras funciones

    Esta es una gran ventaja para Java, donde necesitamos enviar, crear y devolver objetos para hacerlo. Podremos escribir código que sea más confiable, enfocado y más fácil de reutilizar.

  • Gracias a las lambdas, podemos hacer cálculos diferidos. Cuando se envía una expresión lambda como argumento de un método, el compilador la evaluará cuando se llame en el método. Esto es diferente de los argumentos de los métodos normales, que se evalúan inmediatamente.

  • Lambdas hace que escribir pruebas unitarias sea divertido. Nos permiten crear pruebas livianas, limpias, de tamaño pequeño y rápidas de escribir. Podemos eliminar el código bajo prueba usando lambdas. Esto nos permite probar cómo afectarán al código todo tipo de escenarios.

  • Nuevos patrones para aprender.

  • ¡Y mucho más!

Pero basta de agua, en este artículo veremos soluciones alternativas a los ciclos tradicionales. Por supuesto, los ciclos son flexibles, pero esto tiene un precio. break, cambian drásticamente el comportamiento del bucle, lo que nos obliga a comprender no solo lo que el código intenta lograr, continuesino returntambién cómo funciona el bucle. Ahora veremos cómo podemos transformar bucles en código más conciso y legible.

¡Que comience la codificación!

Trabajaremos con artículos. Un artículo tiene un título, autor y varias etiquetas.
private class Article {

    private final String title;
    private final String author;
    private final List<String> tags;

    private Article(String title, String author, List<String> tags) {
        this.title = title;
        this.author = author;
        this.tags = tags;
    }

    public String getTitle() {
        return title;
    }

    public String getAuthor() {
        return author;
    }

    public List<String> getTags() {
        return tags;
    }
}
Cada ejemplo contendrá una solución tradicional que usa bucles y una solución que usa las nuevas características de Java 8. En el primer ejemplo, queremos encontrar el primer artículo de la colección con la etiqueta "Java". Echemos un vistazo a una solución que utiliza un bucle.
public Article getFirstJavaArticle() {

    for (Article article : articles) {
        if (article.getTags().contains("Java")) {
            return article;
        }
    }
    return null;
}
Ahora resolvamos el problema usando operaciones de Stream API.
public Optional<Article> getFirstJavaArticle() {
    return articles.stream()
        .filter(article -> article.getTags().contains("Java"))
        .findFirst();
    }
Muy bueno, ¿no? Primero usamos la operación filterpara buscar todos los artículos con la etiqueta "Java", luego la usamos findFirst()para obtener la primera aparición. Dado que las transmisiones son diferidas y el filtro devuelve una secuencia, este enfoque solo procesará elementos hasta que encuentre la primera coincidencia. Ahora pongamos todos los artículos etiquetados como "Java" en lugar de solo el primero. Primero la solución usando bucles.
public List<Article> getAllJavaArticles() {

    List<Article> result = new ArrayList<>();

    for (Article article : articles) {
        if (article.getTags().contains("Java")) {
            result.add(article);
        }
    }
    return result;
}
Solución mediante operaciones de flujo.
public List<Article> getAllJavaArticles() {
    return articles.stream()
        .filter(article -> article.getTags().contains("Java"))
        .collect(Collectors.toList());
    }
En este ejemplo, utilizamos una operación collectpara acortar el flujo resultante, en lugar de declarar una colección y agregar explícitamente las entradas que coinciden. Hasta ahora, todo bien. Es hora de ver ejemplos que harán que Stream API realmente brille. Agrupemos todos los artículos por autor. Como es habitual, empezamos resolviéndolo mediante bucles:
public Map<String, List<Article>> groupByAuthor() {

    Map<String, List<Article>> result = new HashMap<>();

    for (Article article : articles) {
        if (result.containsKey(article.getAuthor())) {
            result.get(article.getAuthor()).add(article);
        } else {
            ArrayList<Article> articles = new ArrayList<>();
            articles.add(article);
            result.put(article.getAuthor(), articles);
        }
    }
    return result;
}
¿Podemos encontrar una solución limpia a este problema utilizando operaciones de flujo?
public Map<String, List<Article>> groupByAuthor() {
    return articles.stream()
        .collect(Collectors.groupingBy(Article::getAuthor));
}
¡Asombroso! Al utilizar una operación groupingByy una referencia de método getAuthor(), obtenemos un código limpio y legible. Ahora busquemos el resto de las etiquetas utilizadas en la colección. Comencemos con un ejemplo de bucle:
public Set<String> getDistinctTags() {

    Set<String> result = new HashSet<>();

    for (Article article : articles) {
        result.addAll(article.getTags());
    }
    return result;
}
Bien, echemos un vistazo a cómo podemos resolver esto usando operaciones de flujo:
public Set<String> getDistinctTags() {
    return articles.stream()
        .flatMap(article -> article.getTags().stream())
        .collect(Collectors.toSet());
}
¡Fresco! flatmapnos ayuda a aplanar la lista de etiquetas en un único flujo de resultados, que luego usamos collectpara crear el conjunto de retorno.

Posibilidades infinitas

Estos fueron 4 ejemplos de cómo se pueden reemplazar los bucles con código más legible. Asegúrese de consultar la API Stream, ya que este artículo solo ha arañado la superficie. Dominar el nuevo estilo funcional de Java será un desafío para los desarrolladores de programación orientada a objetos, pero es un desafío que debería ser bien recibido. Incluso iré tan lejos como para decir que deberías aprender un lenguaje de programación funcional puro. De esta manera podrá comprender completamente las capacidades y el poder que proporciona. Creo que esto te ayudará a comprender la programación funcional a otro nivel. ¡Así que aprenda programación funcional junto con la vieja programación orientada a objetos y úselas ambas para escribir código aún mejor! Una combinación gratuita de traducciones de dos artículos: Por qué debería adoptar la programación funcional en Java 8 y Evitar los bucles en Java 8
Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION