Pregunta

Tengo algunos datos almacenados como ArrayList . Y cuando quiero hacer una copia de seguridad de estos datos, Java limita dos objetos para siempre. Lo que significa que cuando cambio los valores en los datos ArrayList , estos cambios vienen a la copia de seguridad. Intenté copiar valores de los datos por separado para hacer una copia de seguridad en el bucle, intenté usar el método data.clone () , nada ayuda.

¿Fue útil?

Solución

Creo que necesita .clone () los objetos individuales. La clonación de ArrayList no es "profunda". solo clonará las referencias al objeto.

Otros consejos

Tu pregunta no es muy clara. Si clona () una ArrayList, el clon no se modificará si cambia el contenido del original (es decir, si agrega o elimina elementos), pero es una copia superficial '' así que si cambia los objetos reales en el original, también se cambiarán en el clon.

Si desea hacer una "copia profunda", de modo que los cambios en los objetos reales no afecten las copias de seguridad de ellos en el clon, entonces debe crear una nueva ArrayList y luego pasar por la original y cada elemento, clónelo en el nuevo. Como en

ArrayList backup = new ArrayList();
for (Object obj : data)
   backup.add(obj.clone());

Supongo que data es el nombre de ArrayList que desea respaldar. Si es así, debe saber que clone no es profundo , solo crea una copia del objeto en el que se invoca, que en este caso es la lista. Si fuera un clon profundo, llenaría la nueva lista con clones de los objetos que contiene.

Dado que no es profundo, si cambia los objetos que contiene la lista, la lista de respaldo también mostrará esos cambios, ya que contiene los mismos objetos. La única vez que no verá cambios en la copia de seguridad después de cambiar el " actual " lista es cuando agrega o elimina objetos de la lista actual.

Algunas clases pueden anular clone para que sean profundas, pero no todas. En general, no es algo en lo que pueda confiar. Al crear una copia de seguridad de las colecciones de Java, recuerde clonar también los objetos contenidos o tratar solo con colecciones de objetos inmutables.

Todos estos procesos hacen copias superficiales. Si está cambiando las propiedades de los objetos en la matriz, las dos matrices tienen referencias a la misma instancia.

List org = new java.util.ArrayList();
org.add(instance)
org.get(0).setValue("org val");
List copy = new java.util.ArrayList(org);
org.get(0).setValue("new val");

copy.get (0) .getValue () devolverá " new val " también porque org.get (0) y copy.get (0) devuelve exactamente la misma instancia. Debe realizar una copia profunda de esta manera:

List copy = new java.util.ArrayList();
for(Instance obj : org) {
    copy.add(new Instance(obj)); // call to copy constructor
}

Depende de lo que necesites. Copia superficial (los elementos de la lista son referencias al mismo que en el original):

ArrayList backup = new ArrayList(mylist.size());
backup.addAll(mylist);

Copia profunda (los elementos también son copias):

ArrayList backup = new ArrayList(mylist.size());
for(Object o : mylist) {
    backup.add(o.clone());
}

Suena (si interpreto su pregunta correctamente; es un poco difícil) como si no estuviera copiando los datos a los que se refiere en su ArrayList a su copia de seguridad; estás copiando la referencia.

Es difícil decir exactamente cómo resolver su problema sin saber cuál es su tipo de datos que está almacenando / respaldando, pero solo asegúrese de copiar los elementos de los datos contenidos en ArrayList. Eso significaría, entre otras cosas, hacer cosas como realizar un clon () en los elementos de la lista, pero no en ArrayList (porque eso creará una nueva lista clonada con copias de las referencias a los mismos objetos).

Con respecto al problema de la clonación, una vez que resolví esto serializando toda la colección en una cadena y luego serializándola nuevamente en un nuevo objeto. Esto lo obliga a hacer que todos sus objetos sean serializables y tomar cuando dos objetos realmente quieren hacer referencia a un solo tercer objeto, pero puede ser un buen equilibrio de simplicidad y utilidad.

En realidad, no he intentado esto, pero probablemente podría usar una tubería para serializar dentro y fuera al mismo tiempo exacto, de modo que no esté almacenando 3 copias en la memoria (si es una gran colección)

Aquí hay una clase de copia de seguridad ArrayList totalmente funcional que verifica si ArrayList ya existe. Básicamente es solo un ciclo for-loop a través de la lista y agregarlos manualmente a la nueva lista.

import java.util.ArrayList;

public class Snapshot {
    private ArrayList<Integer> dataBackup;

    public Snapshot(ArrayList<Integer> data)
    {
        dataBackup = new ArrayList<Integer>();
        for(int i = 0; i < data.size(); i++)
        {
            dataBackup.add(data.get(i));
        }
    }

    public ArrayList<Integer> restore()
    {
        return dataBackup;
    }

    public static void main(String[] args)
    {
        ArrayList<Integer> list = new ArrayList<Integer>();
        list.add(1);
        list.add(2);

        Snapshot snap = new Snapshot(list);

        list.set(0, 3);
        list = snap.restore();

        System.out.println(list); // Should output [1, 2]

        list.add(4);
        list = snap.restore();

        System.out.println(list); // Should output [1, 2]
    }
}

Todavía no lo he probado, pero creo que Collections.copy lo hará.

[EDITAR] Ahora, intenté:

static String GetRandomString(int length)
{
  UUID uuid = UUID.randomUUID();
  return uuid.toString().substring(0, length);  
}

public static void main(String[] args)
{
  ArrayList<String> al = new ArrayList<String>(20);
  for (int i = 0; i < 10; i++)
  {
    al.add(GetRandomString(7));
  }
  ArrayList<String> cloneArray = new ArrayList<String>(al);
  Collections.copy(cloneArray, al);
  System.out.println(al);
  System.out.println(cloneArray);
  for (int i = 9; i >= 0; i -= 2)
  {
    al.remove(i);
  }
  System.out.println(al);
  System.out.println(cloneArray);
}

Podría escribir un objeto que envuelva dos ArrayLists. Cualquier cosa escríbala para que agregue, elimine y modifique datos en ambos al mismo tiempo.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top