Conversión de una colección a ArrayList en Java

1. Información general

Convertir colecciones de Java de un tipo a otro es una tarea de programación común. En este tutorial, convertiremos cualquier tipo de colección en una ArrayList .

A lo largo del tutorial, asumiremos que ya tenemos una colección de objetos Foo . A partir de ahí, crearemos una ArrayList utilizando varios enfoques.

2. Definiendo nuestro ejemplo

Pero antes de continuar, modelemos nuestra entrada y salida.

Nuestra fuente puede ser cualquier tipo de colección, así que la declararemos usando la interfaz de Colección :

Collection srcCollection; 

Necesitamos producir una ArrayList con el mismo tipo de elemento:

ArrayList newList;

3. Uso del constructor ArrayList

La forma más sencilla de copiar una colección a una nueva colección es utilizando su constructor.

En nuestra guía anterior de ArrayList, aprendimos que el constructor ArrayList puede aceptar un parámetro de colección:

ArrayList newList = new ArrayList(srcCollection);
  • El nuevo ArrayList contiene una copia superficial de los elementos de Foo en la colección de origen.
  • El orden es el mismo que el de la colección de origen.

La simplicidad del constructor lo convierte en una excelente opción en la mayoría de los escenarios.

4. Uso de la API de Streams

Ahora, aprovechemos la API de Streams para crear una ArrayList a partir de una colección existente :

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

En este fragmento:

  • Tomamos el flujo de la colección de origen y aplicamos el operador collect () para crear una Lista
  • Especificamos ArrayList :: new para obtener el tipo de lista que queremos
  • Este código también producirá una copia superficial.

Si no estuviéramos preocupados por el tipo de lista exacto , podríamos simplificar:

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

Tenga en cuenta que toCollection () y toList () se importan estáticamente desde Collectors . Para obtener más información, consulte nuestra guía sobre recopiladores de Java 8.

5. Copia profunda

Antes mencionamos "copias superficiales". Con eso, queremos decir que los elementos de la nueva lista son exactamente las mismas instancias de Foo que todavía existen en la colección fuente. Por lo tanto, hemos copiado los Foo s en newList por referencia.

Si modificamos el contenido de una instancia de Foo en cualquiera de las colecciones, esa modificación se reflejará en ambas colecciones . Por lo tanto, si queremos modificar los elementos de cualquiera de las colecciones sin modificar la otra, debemos realizar una "copia profunda".

Para realizar una copia profunda de un Foo , creamos una instancia de Foo completamente nueva para cada elemento . En consecuencia, todos los campos de Foo deben copiarse en las nuevas instancias.

Definamos nuestra clase Foo para que sepa cómo copiarse en profundidad:

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); } }

Aquí podemos ver que los campos id y name son int y String . Estos tipos de datos se copian por valor. Por lo tanto, podemos simplemente asignarlos a ambos.

El campo padre es otro Foo , que es una clase. Si Foo se mutó, cualquier código que comparta esa referencia se verá afectado por estos cambios. Tenemos que copiar en profundidad el campo principal .

Ahora podemos volver a nuestra conversión ArrayList . Solo necesitamos que el operador del mapa inserte la copia profunda en el flujo:

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

Podemos modificar el contenido de cualquiera de las colecciones sin afectar a la otra.

Una copia en profundidad puede ser un proceso largo dependiendo de la cantidad de elementos y la profundidad de los datos. El uso de una transmisión en paralelo aquí puede proporcionar un aumento del rendimiento si es necesario.

6. Control del orden de la lista

De forma predeterminada, nuestra secuencia entregará elementos a nuestra ArrayList en el mismo orden en que se encuentran en la colección de origen.

Si queremos cambiar ese orden, podemos aplicar el operador sorted () a la secuencia . Para ordenar nuestros objetos Foo por nombre:

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

Podemos encontrar más detalles sobre el pedido de transmisiones en este tutorial anterior.

7. Conclusión

El constructor ArrayList es una forma eficaz de obtener el contenido de una colección en una nueva ArrayList .

However, if we need to tweak the resulting list, the Streams API provides a powerful way to modify the process.

The code used in this article can be found in its entirety over on GitHub.