Convertendo uma coleção em ArrayList em Java

Convertendo uma coleção em ArrayList em Java

1. Visão geral

A conversão de coleções Java de um tipo para outro é uma tarefa de programação comum. Neste tutorial, converteremos qualquer tipo deCollection em umArrayList.

Ao longo do tutorial, assumiremos que já temos uma coleção de objetosFoo. A partir daí, vamos criar umArrayList using várias abordagens.

2. Definindo nosso exemplo

Mas antes de continuar, vamos modelar nossa entrada e saída.

Nossa fonte pode ser qualquer tipo de coleção, então vamos declará-la usando a interfaceCollection:

Collection srcCollection;

Precisamos produzir umArrayList com o mesmo tipo de elemento:

ArrayList newList;

3. Usando o Construtor ArrayList

A maneira mais simples de copiar uma coleção para uma nova coleção é usando seu construtor.

Em nossoguide to ArrayList anterior, aprendemos que o construtorArrayList pode aceitar um parâmetro de coleção:

ArrayList newList = new ArrayList<>(srcCollection);
  • O novoArrayList contém uma cópia superficial dos elementos Foo na coleção de origem.

  • O pedido é igual ao da coleção de origem.

A simplicidade do construtor o torna uma ótima opção na maioria dos cenários.

4. Usando a API Streams

Agora,let’s take advantage of the Streams API to create an ArrayList from an existing Collection: _ _

ArrayList newList = srcCollection.stream().collect(toCollection(ArrayList::new));

Neste trecho:

  • Pegamos o fluxo da coleção de origem e aplicamos o operadorcollect() para criar umList

  • Nós especificamosArrayList::new para obter o tipo de lista que queremos

  • Este código também produzirá uma cópia superficial.

Se não estivéssemos preocupados com o tipo exato deList, poderíamos simplificar:

List newList = srcCollection.stream().collect(toList());

Observe quetoCollection()etoList() são importados estaticamente deCollectors. Para saber mais, consulte nossoguide on Java 8’s Collectors.

5. Cópia profunda

Antes de mencionarmos "cópias rasas". Com isso, queremos dizer quethe elements in the new list are exactly the same Foo instances que ainda existem na coleção de origem. Portanto, copiamosFoos paranewList por referência.

Se modificarmos o conteúdo de uma instânciaFoo em qualquer coleção quemodification will be reflected in both collections. Portanto, se quisermos modificar os elementos em qualquer coleçãowithout modificando a outra, precisamos realizar uma “cópia profunda”.

Para copiar em profundidade aFoo, nóscreate a completely new Foo instance for each element. Conseqüentemente, todos os camposFoo precisam ser copiados para as novas instâncias.

Vamos definir nossa classeFoo para que ela saiba como se copiar em profundidade:

public class Foo {

    private int id;
    private String name;
    private Foo parent;

    public Foo(int id, String name, Foo parent) {
        this.id = id;
        this.name = name;
        this.parent = parent;
    }

    public Foo deepCopy() {
        return new Foo(
          this.id, this.name, this.parent != null ? this.parent.deepCopy() : null);
    }
}

Aqui podemos ver que os camposidename sãointeString. Esses tipos de dados são copiados por valor. Portanto, podemos simplesmente atribuir os dois.

O campoparent é outroFoo, que é uma classe. SeFoo got sofreu mutação, qualquer código que compartilhe essa referência será afetado por essas alterações. We have to deep copy the parent field.

Agora podemos voltar para a conversão deArrayList. We just need the map operator to insert the deep copy no fluxo:

ArrayList newList = srcCollection.stream()
  .map(foo -> foo.deepCopy())
  .collect(toCollection(ArrayList::new));

Podemos modificar o conteúdo de qualquer coleção sem afetar a outra.

Uma cópia em profundidade pode ser um processo demorado, dependendo do número de elementos e da profundidade dos dados. O uso de um fluxo paralelo aqui pode fornecer um aumento de desempenho, se necessário.

6. Controlando a Ordem da Lista

Por padrão, nosso stream entregará elementos para nossoArrayList na mesma ordem em que são encontrados na coleção de origem.

Se quisermos mudar essa ordemwe could apply the sorted() operator to the stream. Para classificar nossos objetosFoo por nome:

ArrayList newList = srcCollection.stream()
  .sorted(Comparator.comparing(Foo::getName))
  .collect(toCollection(ArrayList::new));

Podemos encontrar mais detalhes sobre a ordenação do fluxo nesteearlier tutorial.

7. Conclusão

O construtorArrayList é uma maneira eficaz de obter o conteúdo de umCollection em um novoArrayList.

No entanto, se precisarmos ajustar a lista resultante, a API do Streams fornece uma maneira poderosa de modificar o processo.

O código usado neste artigo pode ser encontrado em sua totalidadeover on GitHub.