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
maptransforma cada elemento;filterseleciona elementos;reducecombina elementos em um único resultado.collecté uma operação terminal que acumula elementos em uma coleção ou outro contêiner mutável.Collectors.groupingByagrupa elementos por uma função classificadora, retornando umMap.- 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.
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);
}
}