¿Cómo puedo clonar ArrayList
y también clonar sus elementos en Java?
Por ejemplo tengo:
ArrayList<Dog> dogs = getDogs();
ArrayList<Dog> clonedList = ....something to do with dogs....
Y esperaría que los objetos en clonedList
no sean los mismos que en la lista de perros.
java
collections
clone
deep-copy
palig
fuente
fuente
Respuestas:
Deberá iterar sobre los elementos y clonarlos uno por uno, colocando los clones en su matriz de resultados a medida que avanza.
Para que eso funcione, obviamente, tendrá que hacer que su
Dog
clase implemente laCloneable
interfaz y anule elclone()
método.fuente
Yo, personalmente, agregaría un constructor a Dog:
Luego solo itera (como se muestra en la respuesta de Varkhan):
Creo que la ventaja de esto es que no es necesario que juegue con las cosas clonables rotas en Java. También coincide con la forma en que copia las colecciones de Java.
Otra opción podría ser escribir su propia interfaz ICloneable y usarla. De esa manera, podría escribir un método genérico para la clonación.
fuente
cloneList(List<Object>)
oDog(Object)
?Todas las colecciones estándar tienen constructores de copia. Usalos, usalos a ellos.
clone()
fue diseñado con varios errores (vea esta pregunta ), por lo que es mejor evitarlo.Desde Java 2nd Edition , artículo 11: anular juiciosamente el clon
Este libro también describe las muchas ventajas que tienen los constructores de copias sobre Cloneable / clone.
Considere otro beneficio del uso de constructores de copia: suponga que tiene un
HashSet s
y desea copiarlo como aTreeSet
. El método clone no puede ofrecer esta funcionalidad, pero es fácil con un constructor de conversión:new TreeSet(s)
.fuente
Java 8 proporciona una nueva forma de llamar al constructor de copias o al método de clonación en los elementos perros de forma elegante y compacta: Streams , lambdas y recopiladores .
Copiar constructor:
La expresión
Dog::new
se llama referencia de método . Crea un objeto de función que llama a un constructor en elDog
que toma otro perro como argumento.Método de clonación [1]:
Obteniendo un
ArrayList
resultadoO, si tiene que obtener un
ArrayList
respaldo (en caso de que quiera modificarlo más adelante):Actualice la lista en su lugar
Si no necesita conservar el contenido original de la
dogs
lista, puede utilizar elreplaceAll
método y actualizar la lista en su lugar:Todos los ejemplos asumen
import static java.util.stream.Collectors.*;
.Coleccionista para
ArrayList
sEl recopilador del último ejemplo puede convertirse en un método util. Como esto es algo muy común, personalmente me gusta que sea corto y bonito. Me gusta esto:
[1] Nota sobre
CloneNotSupportedException
:Para que esta solución funcione, el
clone
método deDog
no debe declarar que arrojaCloneNotSupportedException
. La razón es quemap
no se permite al argumento lanzar ninguna excepción marcada.Me gusta esto:
Sin embargo, esto no debería ser un gran problema, ya que es la mejor práctica de todos modos. ( Effectice Java, por ejemplo, da este consejo).
Gracias a Gustavo por notar esto.
PD:
Si lo encuentra más bonito, puede usar la sintaxis de referencia del método para hacer exactamente lo mismo:
fuente
List<Dog> clonedDogs = new ArrayList<>(); dogs.stream().parallel().forEach(d -> clonedDogs.add(new Dog(d)));
parallel
llamadaclonedDogs.add
se llama desde varios subprocesos al mismo tiempo. Las versiones que utilizacollect
son seguras para subprocesos. Esta es una de las ventajas del modelo funcional de la biblioteca de flujos, el mismo código puede usarse para flujos paralelos.Unhandled exception type CloneNotSupportedException
encendidod.clone()
. Declarar la excepción o atraparla no la resuelve.Dog
en este ejemplo) no es compatible con la clonación. ¿Estás seguro de que implementa laClonable
interfaz?Básicamente hay tres formas sin iterar manualmente,
1 Usando constructor
2 Usando
addAll(Collection<? extends E> c)
3 Uso del
addAll(int index, Collection<? extends E> c)
método conint
parámetroNB: El comportamiento de estas operaciones será indefinido si la colección especificada se modifica mientras la operación está en progreso.
fuente
Creo que la respuesta verde actual es mala , ¿por qué podrías preguntar?
La forma en que la serialización también es mala, puede que tengas que agregar Serializable por todas partes.
Entonces, cuál es la solución:
Biblioteca Java de clonación profunda La biblioteca de clonación es una pequeña biblioteca Java de código abierto (licencia de Apache) que clona objetos en profundidad. Los objetos no tienen que implementar la interfaz clonable. Efectivamente, esta biblioteca puede clonar CUALQUIER objeto java. Se puede usar, es decir, en implementaciones de caché si no desea que se modifique el objeto en caché o cuando quiera crear una copia profunda de los objetos.
Compruébalo en https://github.com/kostaskougios/cloning
fuente
He encontrado una manera, puede usar json para serializar / deserializar la lista. La lista serializada no contiene ninguna referencia al objeto original cuando no está serializada.
Usando gson:
Puede hacerlo usando jackson y cualquier otra biblioteca json también.
fuente
Siempre he usado esta opción:
fuente
Tendrá que clonar a
ArrayList
mano (iterando sobre él y copiando cada elemento en un nuevoArrayList
), porqueclone()
no lo hará por usted. La razón de esto es que los objetos contenidos en elArrayList
pueden no implementarseClonable
.Editar : ... y eso es exactamente lo que hace el código de Varkhan.
fuente
Una forma desagradable es hacerlo con reflexión. Algo como esto funcionó para mí.
fuente
original
contiene objetos de diferentes clases, creocloneMethod.invoke
que fallará con una excepción cuando se invoque con el tipo de objeto incorrecto. Debido a esto, podría ser mejor recuperar un clon específicoMethod
para cada objeto. O utilice el método de clonaciónObject
(pero dado que está protegido, puede fallar en más casos).Esto copiará en profundidad cada perro
fuente
Los otros carteles son correctos: debe iterar la lista y copiarla en una nueva lista.
Sin embargo ... Si los objetos en la lista son inmutables, no necesita clonarlos. Si su objeto tiene un gráfico de objeto complejo, también deberá ser inmutable.
El otro beneficio de la inmutabilidad es que también son seguros.
fuente
Aquí hay una solución que usa un tipo de plantilla genérica:
fuente
para ustedes los objetos anulan el método clone ()
y llame a .clone () para Vector obj u ArraiList obj ....
fuente
Manera fácil usando commons-lang-2.3.jar esa biblioteca de java para clonar la lista
enlace de descarga commons-lang-2.3.jar
Cómo utilizar
Espero que este pueda ser útil.
:RE
fuente
El paquete
import org.apache.commons.lang.SerializationUtils;
Hay un metodo
SerializationUtils.clone(Object);
Ejemplo
fuente
Acabo de desarrollar una lib que puede clonar un objeto de entidad y un objeto java.util.List. Simplemente descargue el jar en https://drive.google.com/open?id=0B69Sui5ah93EUTloSktFUkctN0U y use el método estático cloneListObject (Lista de listas). Este método no solo clona la Lista sino también todos los elementos de la entidad.
fuente
Lo siguiente funcionó para mí ...
en Dog.java
Aquí, la nueva lista que se creó a partir del método createCopy se crea a través de SerializationUtils.clone (). Por lo tanto, cualquier cambio realizado en la nueva lista no afectará la lista original
fuente
Creo que encontré una manera realmente fácil de hacer una copia profunda de ArrayList. Suponiendo que desea copiar un String ArrayList arrayA.
Avísame si no te funciona.
fuente