image

Access unlimited bootcamps and 650+ courses forever

60
%OFF
Article image
Diego Oliveira
Diego Oliveira16/10/2025 22:57
Share

Adeus, for Loops! Como a Stream API do Java Deixa seu Código Mais Limpo e Poderoso

    Introdução

    Escrever loops for aninhados para filtrar e transformar listas em Java é uma prática comum, mas nem sempre a mais eficiente ou legível. A Stream API oferece uma alternativa mais declarativa, permitindo que operações complexas sejam realizadas de forma concisa e elegante, muitas vezes em uma única linha de código.

    O Paradigma por Trás da Stream API em Java: O que são Streams?

    • O que é um stream? Stream é uma sequência de elementos que suporta operações de agregação.
    • O que é operação de agregação? Agrupar informações e transformá-las em uma só.

    Stream não armazena dados! Stream, em uma tradução literal como fluxo, é um processo de dados em sequência, onde cada etapa transforma, reduz ou filtra os elementos de uma fonte (como Arrays, Collections, etc.).

    Possui funções intermediárias e terminais, mas o que é isso exatamente?

    • As funções intermediárias são aquelas que transformam, filtram ou organizam os dados, sem encerrar o fluxo. Elas retornam um novo stream, permitindo o encadeamento de várias operações.
    • As funções terminais são aquelas que finalizam o fluxo e produzem um resultado concreto, encerrando o processo.

    Explorando o Poder da Stream API de Java: Operações Essenciais

    Funções Intermediárias

    • filter() - Serve para filtrar elementos com base em uma condição. Somente os elementos que satisfazem a expressão booleana passada permanecem no stream.
    List<Integer> numeros = Arrays.asList(1, 2, 3, 4, 5, 6);
    List<Integer> pares = numeros.stream()
      .filter(n -> n % 2 == 0) // Deixa apenas números pares
      .toList();
    System.out.println(pares); // [2, 4, 6]
    
    • map() - É usada para transformar cada elemento do stream em outro tipo de valor ou formato.
    List<String> nomes = Arrays.asList("diego", "ana", "paulo");
    List<String> nomesMaiusculos = nomes.stream()
      .map(String::toUpperCase) // Transforma cada nome em maiúsculo
      .toList();
    System.out.println(nomesMaiusculos); // [DIEGO, ANA, PAULO]
    

    Outras Funções Intermediárias Importantes

    • distinct() - Remove elementos duplicados.
    • sorted() - Ordena os elementos (alfabeticamente ou numericamente).
    • limit(n) - Pega apenas os primeiros n elementos.
    • skip(n) - Ignora os primeiros n elementos.
    • peek() - Usada para “espiar” o conteúdo durante o processamento, geralmente para depuração.
    List<String> lista = Arrays.asList("Diego", "Ana", "Ana", "Paulo", "Lucas", "Luiza");
    
    
    List<String> resultado = lista.stream()
      .filter(nome -> nome.length() > 3) // Deixa apenas nomes com mais de 3 letras
      .distinct()                      // Remove duplicados
      .sorted()                        // Ordena alfabeticamente
      .peek(System.out::println)       // Mostra cada nome durante o fluxo
      .limit(4)                        // Limita aos 4 primeiros resultados
      .toList();
    
    
    System.out.println("Resultado final: " + resultado);
    

    Funções Terminais

    • collect() - Coleta os elementos do stream e os transforma em uma coleção (como List, Set) ou outro tipo de resultado.
    List<Integer> numeros = Arrays.asList(1, 2, 3, 4, 5, 6);
    List<Integer> pares = numeros.stream()
      .filter(n -> n % 2 == 0)   // mantém apenas pares
      .collect(Collectors.toList()); // coleta em uma lista
    System.out.println(pares); // [2, 4, 6]
    
    • forEach() - Executa uma ação para cada elemento do stream. Muito útil para imprimir ou aplicar alguma operação.
    List<String> nomes = Arrays.asList("Diego", "Ana", "Paulo");
    nomes.stream()
      .forEach(System.out::println);
    // Saída:
    // Diego
    // Ana
    // Paulo
    
    • count() - Retorna a quantidade de elementos que passaram pelo stream, útil para estatísticas.
    long quantidadePares = numeros.stream()
      .filter(n -> n % 2 == 0)
      .count();
    System.out.println("Quantidade de pares: " + quantidadePares); // 3
    
    • reduce() - Reduz todos os elementos do stream a um único valor, aplicando uma operação cumulativa, como soma, multiplicação ou concatenação.
    int soma = numeros.stream()
      .reduce(0, (a, b) -> a + b); // soma todos os números
    System.out.println("Soma total: " + soma); // 21
    
    • anyMatch(), allMatch(), noneMatch() - Verificam se algum, todos ou nenhum elemento atende a uma condição.
    boolean temPar = numeros.stream().anyMatch(n -> n % 2 == 0);
    System.out.println("Tem algum número par? " + temPar); // true
    
    • findFirst() / findAny() - Retornam o primeiro ou qualquer elemento do stream que corresponda a um critério. Retornam um Optional.
    Optional<Integer> primeiroPar = numeros.stream()
      .filter(n -> n % 2 == 0)
      .findFirst();
    System.out.println("Primeiro par: " + primeiroPar.orElse(-1)); // 2
    

    Boas Práticas e Erros Comuns na Java Stream API

    • Evitar reusar a mesma stream: Streams em Java são consumidos por operações terminais. Tentar reutilizar o mesmo stream gera IllegalStateException, pois o fluxo de dados já foi “fechado”.
    Exception in thread "main" java.lang.IllegalStateException: stream has already been operated upon or closed
    
    • Preferir operações intermediárias stateless quando possível: Operações stateless não mantêm estado entre os elementos do fluxo.
    List<Integer> numeros = Arrays.asList(1, 2, 3, 4, 5, 6);
    numeros.stream()
         .filter(n -> n % 2 == 0) // stateless
         .map(n -> n * 2)       // stateless
         .forEach(System.out::println);
    

    Em streams grandes, operações stateful podem ser lentas ou causar uso excessivo de memória. Operações stateless permitem paralelização mais eficiente.

    Conclusão

    Como vimos, a Stream API do Java é mais do que uma ferramenta: é uma mudança de paradigma que promove um código mais limpo e funcional. Ao dominar operações como map e filter, você escreve menos e expressa mais.

    Participe

    Agora é sua vez! Adicione seus conhecimentos ao repositório do projeto: https://github.com/diegooilv/stream-api-java! Veja a pasta exemplos/ e adicione um exemplo seu!

    Referências

    Share
    Recommended for you
    Cognizant - Mobile Developer
    Luizalabs - Back-end com Python
    PcD Tech Bradesco - Java & QA Developer
    Comments (0)