题
我有一些数据存储为ArrayList
。当我想备份这些数据时,java会永远绑定两个对象。这意味着当我更改数据中的值data.clone()
时,这些更改将进入备份。我试图将数据中的值分别复制到循环中的备份,尝试使用方法<=> <!>#8212;没有任何帮助。
解决方案
我认为您需要.clone()
单个对象。克隆ArrayList
不是<!>“深<!>”;;它只会克隆对象的引用。
其他提示
你的问题不是很清楚。如果你克隆()一个ArrayList,如果你改变原始的内容(即你添加或删除元素),克隆将不会被修改,但它是<!>“浅拷贝<!>”;因此,如果您更改原始实际对象,它们也将在克隆中更改。
如果要创建<!>“深层复制<!>”,以便对实际对象的更改不会影响它们在克隆中的备份,那么您需要创建一个新的ArrayList然后浏览原始元素并将每个元素克隆到新元素中。如在
ArrayList backup = new ArrayList();
for (Object obj : data)
backup.add(obj.clone());
我假设data
是您要备份的ArrayList
的名称。如果是这样,您应该知道clone
不是深 - 它只会创建调用它的对象的副本,在本例中是列表。如果它是深度克隆,它将用新的列表填充其中对象的克隆。
由于它不深,如果更改列表包含的对象,则备份列表也会显示这些更改,因为它包含相同的对象。在更改<!> quot; current <!>之后,您唯一没有看到备份中的更改list是在当前列表中添加或删除对象时的。
某些类可能会覆盖<=>深入,但不是全部。一般来说,这不是你可以依赖的东西。在创建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个副本(如果它是一个巨大的集合)
这是一个功能齐全的ArrayList备份类,用于检查ArrayList是否已存在。基本上它只是一个循环遍历列表并手动将它们添加到新列表中。
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]
}
}
我还没有尝试过,但我认为Collections.copy会这样做。
[编辑]现在,我试过了:
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);
}
您可以编写一个包装两个ArrayLists的对象。任何东西都写它,以便它同时添加,删除和修改数据。