Combinando diferentes tipos de coleções em Java

Combinando diferentes tipos de coleções em Java

1. Introdução

Neste tutorial rápido, exploraremos diferentes maneiras de combinar coleções em Java.

Exploraremos várias abordagens usando Java e estruturas externas como Guava, Apache, etc. Para a introdução às Coleções, dê uma olhada emat this series here.

2. Bibliotecas externas para trabalhar com coleções

Junto com as abordagens nativas, também usaremos bibliotecas externas. Adicione as seguintes dependências nopom.xml:


    org.apache.commons
    commons-collections4
    4.2


    org.apache.commons
    commons-exec
    1.3


    com.google.guava
    guava
    26.0-jre

As versões mais recentes podem ser encontradas no Maven Central paraCommons,Commons-execeGuava.

3. Combinando Arrays em Java

3.1. Solução Java Nativa

Java vem com um métodovoid arraycopy() embutido que copia um determinado array de origem para o de destino.

Podemos usá-lo da seguinte maneira:

Object[] combined = new Object[first.length + second.length];
System.arraycopy(first, 0, combined, 0, first.length);
System.arraycopy(second, 0, combined, first.length, second.length);

Nesse método, juntamente com os objetos da matriz, também especificamos a posição de onde precisamos copiar e também passamos o parâmetro length.

Esta é uma solução Java nativa, portanto, não requer nenhuma biblioteca externa.

3.2. Usando a API Java 8Stream

Os fluxos oferecem uma maneira eficaz de iterar em vários tipos diferentes de coleções. Para começar com streams, vá paraJava 8 Stream API Tutorial.

Para combinar arrays usando umStream, podemos usar este código:

Object[] combined = Stream.concat(Arrays.stream(first), Arrays.stream(second)).toArray();

Stream.concat() cria um fluxo concatenado no qual os elementos do primeiro fluxo são seguidos pelos elementos do segundo fluxo, que é depois convertido em uma matriz usando o métodotoArray() .

O processo de criação do fluxo é o mesmo em diferentes tipos de coleções. No entanto, podemos coletá-lo de diferentes maneiras para recuperar diferentes estruturas de dados.

Iremos revisitar esse método nas seções 4.2. e 5.2. para ver como podemos usar o mesmo método emListseSets.

3.3. UsandoArrayUtils do Apache Commons

A biblioteca Apache commons nos fornece o métodoaddAll() do pacoteArrayUtils. Nós podemos fornecer a matriz de destino e de origem como parâmetros, e esse método retornará uma matriz combinada:

Object[] combined = ArrayUtils.addAll(first, second);

Esse método também é discutido em detalhes no artigoArray Processing with Apache Commons Lang 3.

3.4. Usando goiaba

O Guava nos fornece o métodoconcat() para o mesmo propósito:

Object [] combined = ObjectArrays.concat(first, second, Object.class);

Ele pode ser usado com diferentes tipos de dados e aceita duas matrizes de origem junto com a classe literal para retornar a matriz combinada.

4. CombinandoList em Java

4.1. Usando o métodoCollection nativoaddAll()

A própria interfaceCollection nos fornece o métodoaddAll(), que adiciona todos os elementos da coleção especificada ao objeto chamador. Isso também é discutido em detalhes emthis example article:

List combined = new ArrayList<>();
combined.addAll(first);
combined.addAll(second);


Uma vez que esse método é fornecido na maioria das interfaces pai da estrutura de coleções, ou seja, a interfaceCollection, ele pode ser aplicado em todos osLists eSets.

4.2. Usando Java 8

Podemos usarStreameCollectors da seguinte maneira para combinarLists:

List combined = Stream.concat(first.stream(), second.stream()).collect(Collectors.toList());


Isso é o mesmo que fizemos no caso deArrays na seção 3.2, mas em vez de convertê-lo em um array, usamos coletores para convertê-lo em lista. Para saber mais sobreCollectors em detalhes, visiteGuide to Java 8’s Collectors.

Também podemos usarflatMaps desta forma:

List combined = Stream.of(first, second).flatMap(Collection::stream).collect(Collectors.toList());


First, we’re using Stream.of() which returns a sequential stream of two lists –  first and second. We’ll then pass it to flatMap which will return the contents of a mapped stream after applying the mapping function. Este método também discutido no artigoMerging Streams in Java.

Para saber mais sobreflatMap, vá parathis example article.

4.3. UsandoListUtils do Apache Commons

CollectionUtils.union faz a união de duas coleções e retorna uma coleção que contém todos os elementos:

List combined = ListUtils.union(first, second);


Este método também é discutido emA Guide to Apache Commons Collections CollectionUtils. Para mais informações, vá para a seção 4.9. deste artigo.

4.4. Usando goiaba

To merge a List using Guava, we’ll use Iterable which consists of the concat() method. Depois de concatenar todas as coleções, podemos obter rapidamente o objetoList combinado, conforme mostrado neste exemplo:

Iterable combinedIterables = Iterables
  .unmodifiableIterable(Iterables.concat(first, second));
List combined = Lists.newArrayList(combinedIterables);





5. CombinandoSet em Java

5.1. Solução Java Simples

Como já discutimos na seção 4.1., A interfaceCollection vem com um métodoaddAll() embutido que pode ser usado para copiarListseSets também:

Set combined = new HashSet<>();
combined.addAll(first);
combined.addAll(second);



5.2. Usando Java 8 Streams

A mesma função que usamos paraList objetos pode ser aplicada aqui:

Set combined = Stream
  .concat(first.stream(), second.stream())
  .collect(Collectors.toSet());


A única diferença notável aqui ao comparar a lista é que em vez de usarCollectors.toList(), estamos usandoCollectors.toSet() para acumular todos os elementos dos dois fluxos fornecidos em um novoSet.

E semelhante aLists, ao usarflatMaps onSets, seria semelhante a:

Set combined = Stream.of(first, second)
  .flatMap(Collection::stream)
  .collect(Collectors.toSet());



5.3. Usando o Apache Commons

Semelhante aoListUtils, também podemos trabalhar com oSetUtils que faz uma união de elementosSet:

Set combined = SetUtils.union(first, second);



5.4. Usando de Guava

A biblioteca Guava nos fornece o métodoSets.union() direto para combinarSets em Java:

Set combined = Sets.union(first, second);





6. CombinandoMap em Java

6.1. Solução Java Simples

Podemos fazer uso da interfaceMap que nos fornece o métodoputAll() que copia todos os mapeamentos do argumento fornecido do objetoMap para o objetoMap chamador :

Map combined = new HashMap<>();
combined.putAll(first);
combined.putAll(second);

6.2. Usando Java 8

Since Java 8, the Map class consists of merge() method which accepts a key, value, and a BiFunction. Podemos usar isso com uma instrução Java 8forEach para obter a funcionalidade de mesclagem:

second.forEach((key, value) -> first.merge(key, value, String::concat));

O terceiro parâmetro, isto é, a função de remapeamento é útil quando o mesmo par de valores-chave está presente nos dois mapas de origem. Esta função especifica o que deve ser feito com esse tipo de valores.

Também podemos usarflatMap assim:

Map combined = Stream.of(first, second)
  .map(Map::entrySet)
  .flatMap(Collection::stream)
  .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, String::concat));

6.3. Usando Apache Commons Exec

Map combined = MapUtils.merge(first, second);

6.4. Usando o Google Guava

Podemos usarImmutableMap fornecido pela biblioteca Guava do Google. Seu métodoputAll() associa todas as chaves e valores do mapa fornecido ao mapa construído:

Map combined = ImmutableMap.builder()
  .putAll(first)
  .putAll(second)
  .build();

7. Conclusão

Neste artigo, passamos por diferentes abordagens para combinar diferentes tipos deCollections. Nós mesclamosarrays,Lists,Sets eMaps.

Como sempre, os trechos de código completos com seus testes de unidade adequados podem ser encontradosover on GitHub.