Domanda

Ho alcuni dati memorizzati come ArrayList . E quando voglio fare il backup di questi dati, Java vincola due oggetti per sempre. Ciò significa che quando modifico i valori nei dati ArrayList queste modifiche arrivano al backup. Ho provato a copiare i valori dai dati separatamente per il backup nel ciclo, ho provato ad usare il metodo data.clone () & # 8212; niente aiuta.

È stato utile?

Soluzione

Penso che sia necessario .clone () i singoli oggetti. La clonazione dell ' ArrayList non è "profonda"; clonerà solo i riferimenti all'oggetto.

Altri suggerimenti

La tua domanda non è molto chiara. Se cloni () un ArrayList, il clone non verrà modificato se cambi il contenuto dell'originale (cioè se aggiungi o rimuovi elementi) ma è una "copia superficiale". quindi se modifichi gli oggetti reali nell'originale, anche questi verranno cambiati nel clone.

Se vuoi fare una "copia profonda", in modo che le modifiche agli oggetti effettivi non influenzino i loro backup nel clone, allora devi creare una nuova ArrayList e poi passare a quella originale e per ogni elemento, clonalo in quello nuovo. Come in

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

Suppongo che data sia il nome dell ' ArrayList di cui si desidera eseguire il backup. In tal caso, dovresti sapere che clone non è deep : crea solo una copia dell'oggetto su cui viene invocato, che in questo caso è l'elenco. Se fosse un clone profondo, riempirebbe il nuovo elenco di cloni degli oggetti al suo interno.

Poiché non è profondo, se si modificano gli oggetti contenuti nell'elenco, anche l'elenco di backup mostrerà tali modifiche, poiché contiene gli stessi oggetti. L'unica volta che non vedrai cambiamenti nel backup dopo aver modificato " corrente " elenco è quando aggiungi o rimuovi oggetti dall'elenco corrente.

Alcune classi possono sostituire clone per essere profonde, ma non tutte. In generale, non è qualcosa su cui puoi fare affidamento. Quando si crea una copia di backup delle raccolte Java, ricordare di clonare anche gli oggetti contenuti o di gestire solo raccolte di oggetti immutabili.

Tutti questi processi creano copie superficiali. Se si modificano le proprietà degli oggetti con nell'array, i due array hanno riferimenti alla stessa istanza.

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 () restituirà " new val " e anche perché org.get (0) e copy.get (0) restituiscono esattamente la stessa istanza. Devi eseguire una copia profonda in questo modo:

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

Dipende da ciò di cui hai bisogno. Copia superficiale (gli elementi nell'elenco sono riferimenti agli stessi dell'originale):

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

Copia profonda (anche gli articoli sono copie):

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

Sembra (se interpreto correttamente la tua domanda; è un po 'difficile) come se non stessi copiando i dati a cui ti riferisci nella tua ArrayList per il tuo backup; stai copiando il riferimento.

È difficile dire esattamente come risolvere il tuo problema senza sapere quale sia il tipo di dati che stai archiviando / eseguendo il backup, ma assicurati solo di copiare gli elementi dei dati contenuti nell'ArrayList. Ciò significherebbe, tra le altre cose, fare cose come eseguire un clone () sugli elementi dell'elenco, ma non su ArrayList (perché ciò creerà un nuovo elenco clonato con copie dei riferimenti agli stessi oggetti).

Per quanto riguarda il problema della clonazione, una volta risolto il problema serializzando l'intera raccolta in una stringa, quindi serializzandola nuovamente in un nuovo oggetto. Questo ti costringe a rendere serializzabili tutti i tuoi oggetti e a prenderli quando due oggetti vogliono davvero fare riferimento a un singolo terzo oggetto, ma può essere un buon equilibrio tra semplicità e utilità.

In realtà, non ho provato questo, ma probabilmente potresti usare una pipe per serializzare dentro e fuori allo stesso tempo esatto in modo da non conservare 3 copie in memoria (se si tratta di un'enorme raccolta)

Ecco una classe di backup ArrayList perfettamente funzionante che controlla se ArrayList esiste già. Fondamentalmente è solo un ciclo for-loop attraverso l'elenco e aggiungendoli manualmente al nuovo elenco.

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]
    }
}

Non l'ho ancora provato, ma penso che Collections.copy lo farà.

[EDIT] Ora, ho provato:

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

Potresti scrivere un oggetto che avvolge due ArrayList. Qualunque cosa lo scriva in modo da aggiungere, rimuovere e modificare i dati in entrambi contemporaneamente.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top