如何在Java中备份ArrayList?

我有一些数据存储为ArrayList 。 当我想备份这些数据时,java会永远绑定两个对象。 这意味着当我更改数据ArrayList值时,此更改将进入备份。 我试图将数据中的值分别复制到循环中的备份,尝试使用方法data.clone() – 没有任何帮助。

我认为你需要.clone()个别对象。 克隆ArrayList不是“深层”; 它只会克隆对象的引用。

你的问题不是很清楚。 如果你克隆()一个ArrayList,如果你改变原始的内容(即你添加或删除元素),克隆将不会被修改,但它是一个“浅拷贝”,所以如果你改变原始的实际对象,他们将也可以在克隆中更改。

如果要进行“深层复制”,以便对实际对象的更改不会影响它们在克隆中的备份,那么您需要创建一个新的ArrayList,然后通过原始对象和每个元素,克隆进入新的。 如在

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

我假设data是您要备份的ArrayList的名称。 如果是这样,你应该知道clone不是很深 – 它只创建一个调用它的对象的副本,在这种情况下是列表。 如果它是深度克隆,它将用新的列表填充其中的对象的克隆。

由于它不深,如果更改列表包含的对象,则备份列表也会显示这些更改,因为它包含相同的对象。 更改“当前”列表后,唯一一次看不到备份中的更改是在当前列表中添加或删除对象时。

有些类可能会将clone重写为深层次,但不是全部。 一般来说,这不是你可以依赖的东西。 在创建Java集合的备份副本时,请记住要么克隆包含的对象,要么只处理不可变对象的集合。

所有这些过程都会生成浅层副本。 如果要在数组中更改对象的属性,则两个数组都引用同一实例。

 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()也将返回"new val" ,因为org.get(0)copy.get(0)返回完全相同的实例。 您必须像这样执行深层复制:

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

取决于你需要的。 浅拷贝(列表中的项目是与原始项目相同的引用):

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

深层复制(项目也是副本):

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

听起来(如果我正确地解释你的问题;这有点困难),就像你没有将你在ArrayList中引用的数据复制到备份中一样; 你正在复制参考。

如果不知道您正在存储/备份的数据类型,很难确切地说明如何解决您的问题,但只是确保您正在复制ArrayList中包含的数据元素。 除了其他方面,这意味着要对列表的元素执行clone(),而不是对ArrayList执行(因为这将创建一个新的克隆列表,其中包含对相同对象的引用的副本)。

关于克隆问题,一旦我通过将整个集合序列化为字符串然后将其序列化为新对象来解决此问题。 这会强制您使所有对象都可序列化,并在两个对象真正想要引用单个第三个对象时进行,但它可以很好地平衡简单性和实用性。

实际上,我没有尝试过这个,但你可能会在同一时间使用管道进行序列化,这样你就不会在内存中存储3个副本(如果它是一个巨大的集合)

这是一个function齐全的ArrayList备份类,用于检查ArrayList是否已存在。 基本上它只是一个循环遍历列表并手动将它们添加到新列表中。

 import java.util.ArrayList; public class Snapshot { private ArrayList dataBackup; public Snapshot(ArrayList data) { dataBackup = new ArrayList(); for(int i = 0; i < data.size(); i++) { dataBackup.add(data.get(i)); } } public ArrayList restore() { return dataBackup; } public static void main(String[] args) { ArrayList list = new ArrayList(); 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] } } 

我还没有尝试过,但我认为Collections.copy会这样做。

[编辑]现在,我试过:

 static String GetRandomString(int length) { UUID uuid = UUID.randomUUID(); return uuid.toString().substring(0, length); } public static void main(String[] args) { ArrayList al = new ArrayList(20); for (int i = 0; i < 10; i++) { al.add(GetRandomString(7)); } ArrayList cloneArray = new ArrayList(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); } 

您可以编写一个包装两个ArrayLists的对象。 任何东西都写它,以便它同时添加,删除和修改两者中的数据。