Tengo un ArrayList
y quiero copiarlo exactamente. Uso clases de utilidad cuando es posible bajo la suposición de que alguien pasó algún tiempo corrigiendo. Entonces, naturalmente, termino con la Collections
clase que contiene un método de copia.
Supongamos que tengo lo siguiente:
List<String> a = new ArrayList<String>();
a.add("a");
a.add("b");
a.add("c");
List<String> b = new ArrayList<String>(a.size());
Collections.copy(b,a);
Esto falla porque básicamente cree b
que no es lo suficientemente grande como para aguantar a
. Sí, sé que b
tiene el tamaño 0, pero ahora debería ser lo suficientemente grande, ¿no? Si tengo que llenar b
primero, entonces se Collections.copy()
convierte en una función completamente inútil en mi mente. Entonces, a excepción de la programación de una función de copia (que voy a hacer ahora), ¿hay una manera adecuada de hacerlo?
java
list
collections
copy
Jasper Floor
fuente
fuente
Respuestas:
Vocación
crea una copia superficial de
a
dentrob
. Todos los elementos existirán dentrob
exactamente en el mismo orden en que estabana
(suponiendo que tuviera un orden).Del mismo modo, llamando
También crea una copia superficial de
a
dentrob
. Si el primer parámetro,b
no tiene suficiente capacidad (no tamaño) para contener todosa
los elementos, arrojará unIndexOutOfBoundsException
. La expectativa es que no se requerirán asignacionesCollections.copy
para trabajar, y si las hay, arroja esa excepción. Es una optimización requerir que la colección copiada sea preasignada (b
), pero generalmente no creo que la función valga la pena debido a las verificaciones requeridas dadas las alternativas basadas en el constructor como la que se muestra arriba que no tienen efectos secundarios extraños.Para crear una copia profunda
List
, a través de cualquiera de los mecanismos, tendría que tener un conocimiento complejo del tipo subyacente. En el caso deString
s, que son inmutables en Java (y .NET para el caso), ni siquiera necesita una copia profunda. En el caso deMySpecialObject
, necesita saber cómo hacer una copia profunda y no es una operación genérica.Nota: La respuesta originalmente aceptada fue el resultado principal para
Collections.copy
Google, y fue completamente erróneo como se señala en los comentarios.fuente
b
tiene una capacidad de 3, pero un tamaño de 0. El hecho de queArrayList
tenga algún tipo de capacidad de almacenamiento intermedio es un detalle de implementación: no es parte de laList
interfaz, por loCollections.copy(List, List)
que no la usa. Sería feo que fuera un caso especialArrayList
.Como MrWiggles ha indicado, usar el constructor ArrayList que toma una colección es la forma de hacerlo en el ejemplo proporcionado.
Para escenarios más complicados (que bien pueden incluir su código real), puede encontrar útiles las colecciones dentro de Guava .
fuente
Solo haz:
ArrayList tiene un constructor que aceptará otra Colección para copiar los elementos de
fuente
String
objetos son inmutables.La respuesta de Stephen Katulka (respuesta aceptada) es incorrecta (la segunda parte). Explica que
Collections.copy(b, a);
hace una copia profunda, que no lo hace. Ambos,new ArrayList(a);
yCollections.copy(b, a);
solo hacer una copia superficial. La diferencia es que el constructor asigna nueva memoria, ycopy(...)
no lo hace, lo que la hace adecuada en casos en los que puede reutilizar matrices, ya que tiene una ventaja de rendimiento allí.La API estándar de Java intenta desalentar el uso de copias profundas, ya que sería malo que los nuevos codificadores lo usen regularmente, lo que también puede ser una de las razones por las
clone()
que no es público de forma predeterminada.El código fuente
Collections.copy(...)
se puede ver en la línea 552 en: http://www.java2s.com/Open-Source/Java-Document/6.0-JDK-Core/Collections-Jar-Zip-Logging-regex/java/util/ Collections.java.htmSi necesita una copia profunda, debe iterar sobre los elementos manualmente, utilizando un bucle for y clone () en cada objeto.
fuente
La forma más sencilla de copiar una lista es pasarla al constructor de la nueva lista:
b
será una copia superficial dea
Mirando la fuente de
Collections.copy(List,List)
(nunca lo había visto antes) parece ser para hacer frente a los elementos índice por índice. usarList.set(int,E)
así el elemento 0 sobreescribirá el elemento 0 en la lista de destino, etc.fuente
No establece el tamaño. Establece la capacidad inicial (es decir, cuántos elementos puede caber antes de que necesite cambiar su tamaño). Una forma más simple de copiar en este caso es:
fuente
Como hoijui menciona. La respuesta seleccionada de Stephen Katulka contiene un comentario sobre Collections.copy que es incorrecto. El autor probablemente lo aceptó porque la primera línea de código estaba haciendo la copia que quería. La llamada adicional a Collections.copy solo se copia nuevamente. (Resultando que la copia ocurre dos veces).
Aquí hay un código para probarlo.
fuente
La mayoría de las respuestas aquí no se dan cuenta del problema, el usuario quiere tener una COPIA de los elementos de la primera lista a la segunda lista, los elementos de la lista de destino son objetos nuevos y no hacen referencia a los elementos de la lista original. (significa que cambiar un elemento de la segunda lista no debería cambiar los valores para el elemento correspondiente de la lista fuente). Para los objetos mutables no podemos usar el constructor ArrayList (Colección) porque simplemente se referirá al elemento original de la lista y no copiará. Debe tener un clonador de lista para cada objeto al copiar.
fuente
¿Por qué no usas el
addAll
método?incluso si tiene elementos existentes en bo desea colocar algunos elementos después de ellos, como:
fuente
Si desea copiar una ArrayList, cópiela usando:
fuente
Las cadenas se pueden copiar en profundidad con
porque son inmutables Cualquier otro objeto no -> necesita iterar y hacer una copia usted mismo.
fuente
b
apunta al mismoString
objeto correspondiente ena
. Sin embargo, esto no es importante porque, como usted señala, losString
objetos son inmutables.fuente
Cualquier otro objeto no -> necesita iterar y hacer una copia usted mismo.
Para evitar esto, implemente Cloneable.
....
fuente
El siguiente resultado ilustra los resultados del uso de copy constructor y Collections.copy ():
La fuente del programa completo está aquí: copia de la Lista Java . Pero el resultado es suficiente para ver cómo se comporta java.util.Collections.copy ().
fuente
Y si está utilizando google guava, la solución de una línea sería
Esto crea una instancia de lista de matriz mutable.
fuente
Con Java 8 siendo nulo-seguro, puede usar el siguiente código.
O usando un coleccionista
fuente
Copiar no es inútil si imagina el caso de uso para copiar algunos valores en una colección existente. Es decir, desea sobrescribir elementos existentes en lugar de insertar.
Un ejemplo: a = [1,2,3,4,5] b = [2,2,2,2,3,3,3,3,3,4,4,4,] a.copia (b) = [1,2,3,4,5,3,3,3,3,4,4,4]
Sin embargo, esperaría un método de copia que tomaría parámetros adicionales para el índice de inicio de la colección de origen y destino, así como un parámetro para el recuento.
Ver Java BUG 6350752
fuente
Para comprender por qué Collections.copy () arroja una IndexOutOfBoundsException aunque haya hecho que la matriz de respaldo de la lista de destinos sea lo suficientemente grande (a través de la llamada size () en la lista de origen), vea la respuesta de Abhay Yadav en esta pregunta relacionada: Cómo copie un java.util.List en otro java.util.List
fuente