una otra metodo lista copiar java collections clone deep-copy

java - metodo - copiar una lista a otra c#



¿Cómo clonar ArrayList y también clonar su contenido? (17)

Acabo de desarrollar una biblioteca 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.

¿Cómo puedo clonar un 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 espero que los objetos en clonedList no sean los mismos que en la lista de perros.


Aquí hay una solución que usa un tipo de plantilla genérica:

public static <T> List<T> copyList(List<T> source) { List<T> dest = new ArrayList<T>(); for (T item : source) { dest.add(item); } return dest; }


Básicamente hay tres formas sin iterar manualmente,

1 usando constructor

ArrayList<Dog> dogs = getDogs(); ArrayList<Dog> clonedList = new ArrayList<Dog>(dogs);

2 Usando addAll(Collection<? extends E> c)

ArrayList<Dog> dogs = getDogs(); ArrayList<Dog> clonedList = new ArrayList<Dog>(); clonedList.addAll(dogs);

3 Usando el método addAll(int index, Collection<? extends E> c) con parámetro int

ArrayList<Dog> dogs = getDogs(); ArrayList<Dog> clonedList = new ArrayList<Dog>(); clonedList.addAll(0, dogs);

NB: El comportamiento de estas operaciones será indefinido si la colección especificada se modifica mientras la operación está en curso.


Creo que encontré una manera muy fácil de hacer una copia profunda de ArrayList. Suponiendo que desea copiar una matriz ArrayList StringA.

ArrayList<String>arrayB = new ArrayList<String>(); arrayB.addAll(arrayA);

Déjame saber si no te funciona.


Deberá clonar la ArrayList a mano (iterando sobre ella y copiando cada elemento en una nueva ArrayList ), porque clone() no lo hará por usted. La razón de esto es que los objetos contenidos en el ArrayList no pueden implementar Clonable sí mismos.

Edición : ... y eso es exactamente lo que hace el código de Varkhan.


Deberá iterar en los elementos y clonarlos uno por uno, colocando los clones en la matriz de resultados a medida que avanza.

public static List<Dog> cloneList(List<Dog> list) { List<Dog> clone = new ArrayList<Dog>(list.size()); for (Dog item : list) clone.add(item.clone()); return clone; }

Para que funcione, obviamente, tendrá que conseguir que su objeto Dog implemente la interfaz Cloneable y el método clone ().


El paquete import org.apache.commons.lang.SerializationUtils;

Hay un método SerializationUtils.clone(Object);

Ejemplo

this.myObjectCloned = SerializationUtils.clone(this.object);


He encontrado una forma, puede usar json para serializar / deserializar la lista. La lista serializada no contiene ninguna referencia al objeto original cuando no se serializa.

Utilizando gson:

List<CategoryModel> originalList = new ArrayList<>(); // add some items later String listAsJson = gson.toJson(originalList); List<CategoryModel> newList = new Gson().fromJson(listAsJson, new TypeToken<List<CategoryModel>>() {}.getType());

Puedes hacerlo usando jackson y cualquier otra biblioteca json también.


Java 8 proporciona una nueva forma de llamar al constructor de copia o al método de clonación en los elementos de forma elegante y compacta: arroyos , lambdas y colectores .

Copia constructor:

List<Dog> clonedDogs = dogs.stream().map(Dog::new).collect(toList());

La expresión Dog::new se llama referencia de método . Crea una función de objetos que llama a un constructor en Dog que toma a otro dog como argumento.

Método de clonación [1]:

List<Dog> clonedDogs = dogs.stream().map(d -> d.clone()).collect(toList());

Consiguiendo un ArrayList como resultado

O, si tiene que recuperar una ArrayList (en caso de que quiera modificarla más adelante):

ArrayList<Dog> clonedDogs = dogs.stream().map(Dog::new).collect(toCollection(ArrayList::new));

Actualizar la lista en su lugar

Si no necesita mantener el contenido original de la lista de dogs , puede usar el método replaceAll y actualizar la lista en su lugar:

dogs.replaceAll(Dog::new);

Todos los ejemplos suponen import static java.util.stream.Collectors.*; .

Coleccionista para ArrayList s

El recopilador del último ejemplo se puede convertir en un método util. Ya que esto es algo muy común, personalmente me gusta que sea corto y bonito. Me gusta esto:

ArrayList<Dog> clonedDogs = dogs.stream().map(d -> d.clone()).collect(toArrayList()); public static <T> Collector<T, ?, ArrayList<T>> toArrayList() { return Collectors.toCollection(ArrayList::new); }

[1] Nota sobre la CloneNotSupportedException :

Para que esta solución funcione, el método de clone de Dog no debe declarar que lanza la CloneNotSupportedException . El motivo es que el argumento para map no tiene permitido lanzar excepciones comprobadas.

Me gusta esto:

// Note: Method is public and returns Dog, not Object @Override public Dog clone() /* Note: No throws clause here */ { ...

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 utilizar la sintaxis de referencia del método para hacer exactamente lo mismo:

List<Dog> clonedDogs = dogs.stream().map(Dog::clone).collect(toList());


Los otros carteles son correctos: debe iterar la lista y copiar 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 tendrá que ser inmutable.

El otro beneficio de la inmutabilidad es que también son seguros para hilos.


Siempre he usado esta opción:

ArrayList<Dog> clonedList = new ArrayList<Dog>(name_of_arraylist_that_you_need_to_Clone);


Todas las colecciones estándar tienen copia constructores. Usalos, usalos a ellos.

List<Double> original = // some list List<Double> copy = new ArrayList<Double>(original); //This does a shallow copy

clone() fue diseñado con varios errores (vea esta pregunta ), así que es mejor evitarlo.

De Effective Java 2nd Edition , ítem 11: sobrescribir clones con criterio

Dados todos los problemas asociados con Cloneable, es seguro decir que otras interfaces no deberían extenderlo, y que las clases diseñadas para herencia (Artículo 17) no deberían implementarlo. Debido a sus muchas deficiencias, algunos programadores expertos simplemente eligen nunca anular el método de clonación y nunca invocarlo, excepto, quizás, para copiar matrices. Si diseña una clase para herencia, tenga en cuenta que si elige no proporcionar un método de clon protegido con buen comportamiento, será imposible que las subclases implementen Cloneable.

Este libro también describe las muchas ventajas que los constructores de copias tienen sobre Cloneable / clone.

  • No confían en un mecanismo de creación de objetos extralingüísticos propensos a los riesgos.
  • No exigen el cumplimiento inaplicable de convenciones poco documentadas
  • No entran en conflicto con el uso adecuado de los campos finales.
  • No lanzan excepciones comprobadas innecesarias.
  • No requieren moldes.

Considere otro beneficio de usar los constructores de copia: HashSet s que tiene un HashSet s y desea copiarlo como un TreeSet . El método de clonación no puede ofrecer esta funcionalidad, pero es fácil con un constructor de conversión: new TreeSet(s) .


Una forma desagradable es hacerlo con reflexión. Algo como esto funcionó para mí.

public static <T extends Cloneable> List<T> deepCloneList(List<T> original) { if (original == null || original.size() < 1) { return new ArrayList<>(); } try { int originalSize = original.size(); Method cloneMethod = original.get(0).getClass().getDeclaredMethod("clone"); List<T> clonedList = new ArrayList<>(); // noinspection ForLoopReplaceableByForEach for (int i = 0; i < originalSize; i++) { // noinspection unchecked clonedList.add((T) cloneMethod.invoke(original.get(i))); } return clonedList; } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) { System.err.println("Couldn''t clone list due to " + e.getMessage()); return new ArrayList<>(); } }


Una forma sencilla de utilizar commons-lang-2.3.jar esa biblioteca de Java para clonar la lista

Enlace descarga commons-lang-2.3.jar

Cómo utilizar

oldList......... List<YourObject> newList = new ArrayList<YourObject>(); foreach(YourObject obj : oldList){ newList.add((YourObject)SerializationUtils.clone(obj)); }

Espero que este pueda ser de ayuda.

:RE


Yo, personalmente, agregaría un constructor a Dog:

class Dog { public Dog() { ... } // Regular constructor public Dog(Dog dog) { // Copy all the fields of Dog. } }

Entonces simplemente iterar (como se muestra en la respuesta de Varkhan):

public static List<Dog> cloneList(List<Dog> dogList) { List<Dog> clonedList = new ArrayList<Dog>(dogList.size()); for (Dog dog : dogList) { clonedList.add(new Dog(dog)); } return clonedList; }

Considero que la ventaja de esto es que no es necesario joder 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 tu propia interfaz ICloneable y usarla. De esa manera usted podría escribir un método genérico para la clonación.


para que los objetos sobrescriban el método clone ()

class You_class { int a; @Override public You_class clone() { You_class you_class = new You_class(); you_class.a = this.a; return you_class; } }

y llame a .clone () para Vector obj o ArraiList obj ....


Creo que la respuesta verde actual es mala , ¿por qué podría preguntar?

  • Puede requerir agregar mucho código.
  • Requiere que enumere todas las listas que se copiarán y haga esto

La forma en que la serialización también es mala, es posible que tenga que agregar Serializable por todas partes.

Entonces, cuál es la solución:

Biblioteca de clonación profunda de Java La biblioteca de clonación es una biblioteca java pequeña de código abierto (licencia de apache) que clona objetos en profundidad. Los objetos no tienen que implementar la interfaz Cloneable. Efectivamente, esta biblioteca puede clonar CUALQUIER objeto java. Se puede usar, por ejemplo, en implementaciones de caché si no desea que se modifique el objeto almacenado en caché o cuando quiera crear una copia en profundidad de los objetos.

Cloner cloner=new Cloner(); XX clone = cloner.deepClone(someObjectOfTypeXX);

Compruébelo en https://github.com/kostaskougios/cloning