Atualizado: 21/09/2025

Este conteúdo é original e não foi gerado por inteligência artificial.

Transformação de Streams em Coleções com o Método collect em Java

As operações da Stream API processam dados de forma eficiente e preguiçosa, mas o resultado final de um pipeline geralmente precisa ser armazenado em uma estrutura de dados concreta. O método terminal collect é a "ponte" que permite transformar os elementos de um stream de volta em uma coleção, como uma List, Set ou Map.

A forma mais comum de usar collect é em conjunto com a classe de utilitários java.util.stream.Collectors.

Coletando em Listas e Conjuntos (List e Set)

Os coletores mais básicos são toList() e toSet().

  • Collectors.toList(): Acumula os elementos do stream em uma List. Não há garantia sobre qual implementação específica de List será retornada (pode ser um ArrayList ou outra).
  • Collectors.toSet(): Acumula os elementos em um Set, o que remove automaticamente elementos duplicados.
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

public class CollectExample {
    public static void main(String[] args) {
        List<String> phones = List.of("iPhone 15", "Pixel 8", "Galaxy S24",
                                       "Xiaomi 14", "Pixel 8", "iPhone 15");

        List<String> phonesList = phones.stream().collect(Collectors.toList());
        System.out.println("Lista resultante: " + phonesList);

        Set<String> phonesSet = phones.stream().collect(Collectors.toSet());
        System.out.println("Conjunto resultante: " + phonesSet);
    }
}

Saída:

Lista resultante: [iPhone 15, Pixel 8, Galaxy S24, Xiaomi 14, Pixel 8, iPhone 15]
Conjunto resultante: [Pixel 8, iPhone 15, Galaxy S24, Xiaomi 14]

Coletando em Mapas (Map)

O coletor Collectors.toMap() é usado para transformar os elementos do stream em um Map. É necessário fornecer duas funções: uma para gerar a chave e outra para gerar o valor de cada elemento.

import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

record Phone(String name, int price) {}

public class CollectToMapExample {
    public static void main(String[] args) {
        Stream<Phone> phoneStream = Stream.of(
            new Phone("iPhone 15", 999),
            new Phone("Pixel 8", 799),
            new Phone("Samsung Galaxy S24", 899)
        );

        Map<String, Integer> phonesMap = phoneStream.collect(
            Collectors.toMap(Phone::name, Phone::price)
        );

        phonesMap.forEach((key, value) -> System.out.println(key + ": " + value + " USD"));
    }
}

Lidando com Chaves Duplicadas no toMap

Um problema comum ocorre se o stream contiver elementos que geram a mesma chave. A versão padrão de Collectors.toMap() lançará uma IllegalStateException. Para evitar isso, use a versão sobrecarregada que aceita uma terceira função, chamada de "função de mesclagem" (merge function), que define como resolver a colisão.

Stream<Phone> phoneStreamWithDuplicates = Stream.of(
    new Phone("iPhone 15", 999),
    new Phone("Pixel 8", 799),
    new Phone("iPhone 15", 1099) // Chave duplicada
);

// A função de mesclagem (v1, v2) -> v2 diz: "em caso de colisão, use o valor do segundo elemento".
Map<String, Integer> phonesMap = phoneStreamWithDuplicates.collect(
    Collectors.toMap(
        Phone::name,
        Phone::price,
        (existingValue, newValue) -> newValue // Função de mesclagem
    )
);
System.out.println(phonesMap); // Saída: {Pixel 8=799, iPhone 15=1099}

Especificando a Coleção de Destino

Se você precisa que o resultado seja uma implementação específica, como um HashSet ou LinkedList, use Collectors.toCollection(). Este método aceita um Supplier que cria uma nova instância da coleção desejada.

import java.util.HashSet;
import java.util.stream.Collectors;
import java.util.stream.Stream;

HashSet<String> phoneSet = Stream.of("iPhone 15", "Pixel 8", "Galaxy S24", "Pixel 8")
                                 .collect(Collectors.toCollection(HashSet::new));

A expressão HashSet::new é uma referência de método que atua como Supplier.

A Sobrecarga Manual de collect

Para entender o que acontece "por baixo dos panos", existe uma versão de collect que aceita três argumentos. Esta forma é a base sobre a qual os coletores da classe Collectors são construídos.

<R> R collect(Supplier<R> supplier, BiConsumer<R, T> accumulator, BiConsumer<R, R> combiner)
  • supplier: Cria o contêiner de resultado (ex: ArrayList::new).
  • accumulator: Adiciona um elemento do stream ao contêiner (ex: ArrayList::add).
  • combiner: Une dois contêineres. É usada apenas em streams paralelos para combinar os resultados parciais.
import java.util.ArrayList;
import java.util.stream.Stream;

ArrayList<String> phones = Stream.of("iPhone 15", "Pixel 8", "Galaxy S24")
    .collect(
        ArrayList::new,   // supplier
        ArrayList::add,   // accumulator
        ArrayList::addAll // combiner
    );

Resumo

  • O método collect é uma operação terminal que transforma um stream em uma coleção ou outra estrutura de dados.
  • A classe Collectors fornece implementações prontas para as necessidades mais comuns (toList, toSet, toMap).
  • Ao usar toMap, esteja preparado para lidar com chaves duplicadas usando a função de mesclagem.
  • Para obter uma implementação específica de coleção (como HashSet), use Collectors.toCollection(Supplier).
  • A sobrecarga de collect com três argumentos (supplier, accumulator, combiner) oferece controle total sobre o processo de coleta.
Política de Privacidade

Copyright © www.programicio.com Todos os direitos reservados

É proibida a reprodução do conteúdo desta página sem autorização prévia do autor.

Contato: programicio@gmail.com