Da trilha de Java Este conceito ainda não saiu como card do dia. ir para o card de hoje

Java Coleções Avançado

Streams

A API de Streams do Java, introduzida no Java 8, permite processar coleções de forma declarativa e funcional. Um stream é uma sequência de elementos que suporta operações em pipeline, como map, filter e reduce, possibilitando código mais conciso e expressivo.

As operações em streams são divididas em intermediárias (como map e filter) e terminais (como collect e reduce). As intermediárias são preguiçosas (lazy): elas não executam nada até que uma operação terminal seja chamada. Isso permite otimizações, como fusão de operações e curto-circuito.

A operação collect é uma das mais poderosas, permitindo acumular os elementos em estruturas como listas, conjuntos ou mapas. Com Collectors.groupingBy, podemos agrupar elementos por uma função classificadora, gerando um Map onde as chaves são os resultados da classificação e os valores são listas (ou outros tipos) dos elementos correspondentes.

Neste card, exploraremos como combinar essas operações para processar dados de forma eficiente, entender o comportamento preguiçoso dos streams e aplicar Collectors.groupingBy para agrupamentos complexos.

Pontos-chave

  • map transforma cada elemento; filter seleciona elementos; reduce combina elementos em um único resultado.
  • collect é uma operação terminal que acumula elementos em uma coleção ou outro contêiner mutável.
  • Collectors.groupingBy agrupa elementos por uma função classificadora, retornando um Map.
  • Streams são preguiçosos: operações intermediárias não são executadas até que uma operação terminal seja chamada.
  • O pipeline de stream pode ser reutilizado? Não, um stream só pode ser consumido uma vez.
StreamsDemo.java
import java.util.*;
import java.util.stream.*;

public class StreamsDemo {
    public static void main(String[] args) {
        List<String> palavras = Arrays.asList("java", "stream", "api", "collect", "group", "map", "filter");

        // Exemplo de map, filter e reduce: soma o comprimento das palavras que começam com 'c'
        int soma = palavras.stream()
                .filter(p -> p.startsWith("c"))
                .mapToInt(String::length)
                .reduce(0, Integer::sum);
        System.out.println("Soma dos comprimentos das palavras que começam com 'c': " + soma);

        // Exemplo de collect: coletar em uma lista
        List<String> comMaiusculas = palavras.stream()
                .map(String::toUpperCase)
                .collect(Collectors.toList());
        System.out.println("Palavras em maiúsculas: " + comMaiusculas);

        // Exemplo de groupingBy: agrupar palavras pelo primeiro caractere
        Map<Character, List<String>> porPrimeiraLetra = palavras.stream()
                .collect(Collectors.groupingBy(p -> p.charAt(0)));
        System.out.println("Agrupadas por primeira letra: " + porPrimeiraLetra);

        // Demonstração de preguiça: sem operação terminal, nada acontece
        Stream<String> streamPreguicoso = palavras.stream()
                .filter(p -> {
                    System.out.println("Filtrando: " + p);
                    return p.length() > 3;
                });
        System.out.println("Nada foi impresso ainda, pois não há operação terminal.");
        long count = streamPreguicoso.count(); // operação terminal
        System.out.println("Contagem de palavras com mais de 3 letras: " + count);
    }
}

Exercícios

  1. 1
    Fácil

    Soma dos quadrados dos números pares

    Dada uma lista de inteiros, use streams para filtrar os números pares, calcular o quadrado de cada um e somar todos os resultados. Imprima a soma.

    Resolver
  2. 2
    Médio

    Agrupamento de palavras por comprimento

    Dada uma lista de palavras, agrupe-as pelo seu comprimento usando Collectors.groupingBy. Imprima o mapa resultante.

    Resolver
  3. 3
    Desafio

    Processamento de transações com streams

    Dada uma lista de transações (cada uma com id, tipo e valor), use streams para:

    1. Filtrar transações do tipo "CREDITO".
    2. Agrupar por id usando Collectors.groupingBy.
    3. Para cada grupo, somar os valores usando Collectors.summingDouble.
    4. Imprimir o mapa resultante (id -> soma).

    Considere a classe Transacao já definida.

    Resolver

Continue estudando