Coletar um fluxo Java em uma coleção imutável

Coletar um fluxo Java em uma coleção imutável

1. Introdução

Neste artigo rápido, vamos dar uma olhada em várias maneiras de coletar JavaStreams emCollections – imutáveis, que requerem uma abordagem especial porqueCollectors padrão funciona apenas com estruturas de dados mutáveis.

2. Dependência do Maven

Vamos usar a biblioteca Guava do Google para gerar alguns de nossos exemplos:


    com.google.guava
    guava
    22.0

Podemos obter a versão mais recente dessa dependência emhere.

3. UsandocollectingAndThen() de Java

O métodocollectingAndThen() da classeCollectors de Java aceita umCollector e umfinisherFunction que é aplicado ao resultado retornado deCollector:

@Test
public void whenUsingCollectingToImmutableList_thenSuccess() {
    List givenList = Arrays.asList("a", "b", "c");
    List result = givenList.stream()
      .collect(collectingAndThen(toList(), ImmutableList::copyOf));

    System.out.println(result.getClass());
}

Já que não podemos usar toCollection() Collector diretamente,, precisamos coletar elementos para uma lista temporária e, em seguida, construir uma lista imutável a partir dela.

Neste exemplo, estamos convertendo aStream emList usando o coletortoList() e criando umImmutableList. OImmutableList faz parte da biblioteca Guava. Se registrarmos a saída no console, obteremos a classe do

Se registrarmos a saída no console, obteremos a classe da implementaçãoList subjacente:

class com.google.common.collect.RegularImmutableList

4. UsandoCollectors de Guava

Começando com Guava 21, com cada classe imutável vem um acompanhanteCollector que é tão fácil de usar quantoCollectors: padrão

@Test
public void whenCollectToImmutableList_thenSuccess() {
    List list = IntStream.range(0, 9)
      .boxed()
      .collect(ImmutableList.toImmutableList());
}

A instância resultante é oRegularImmutableList:

class com.google.common.collect.RegularImmutableList

5. Construindo um coletor personalizado

Agora, vamos dar um passo adiante e implementar nossoCollector personalizado. Para atingir esse objetivo, vamos usar o métodoCollector.of() estático:

public static  Collector, List> toImmutableList() {
    return Collector.of(ArrayList::new, List::add,
    (left, right) -> {
      left.addAll(right);
      return left;
    }, Collections::unmodifiableList);
}

Para saber mais sobre como implementarCollectors personalizado, dê uma olhada na Seção 4 dethis article. E é isso. O método acima faz parte da nossa classe personalizada

Podemos usá-lo agora como qualquer outroCollectors integrado:

@Test
public void whenCollectToMyImmutableListCollector_thenSuccess() {
    List givenList = Arrays.asList("a", "b", "c", "d");
    List result = givenList.stream()
      .collect(MyImmutableListCollector.toImmutableList());
}

Finalmente, vamos verificar o resultado:

class java.util.Collections$UnmodifiableRandomAccessList