如何在 Java 中备份 ArrayList?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/303098/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to backup ArrayList in Java?
提问by Stella
I have some data stored as ArrayList
. And when I want to backup this data,java bounds two objects forever. Which means when I change values in data ArrayList
this changes come to backup. I tried to copy values from data separately to backup in the loop, tried to use method data.clone()
— nothing helps.
我有一些数据存储为ArrayList
. 当我想备份这些数据时,java 永远绑定了两个对象。这意味着当我更改数据中的值时,ArrayList
这些更改会备份。我尝试将数据中的值分别复制到循环中的备份,尝试使用方法data.clone()
- 没有任何帮助。
采纳答案by activout.se
I think you need to .clone()
the individual objects. Cloning the ArrayList
is not "deep"; it will only clone the references to the object.
我认为你需要.clone()
单个对象。克隆ArrayList
并不“深”;它只会克隆对对象的引用。
回答by Grant Limberg
You could write an object that wraps two ArrayLists. Anything write it so that it adds, removes, and modifies data in both at the same time.
您可以编写一个包装两个 ArrayList 的对象。任何编写它以便它同时添加、删除和修改数据。
回答by Paul Sonier
It sounds (if I interpret your question properly; it's a little tough) like you're not copying the data that you're referring to in your ArrayList to your backup; you're copying the reference.
听起来(如果我正确解释您的问题;这有点困难)就像您没有将您在 ArrayList 中引用的数据复制到备份;你正在复制参考。
It's hard to say exactly how to solve your problem without knowing what your data type is that you're storing / backing up, but just be sure that you're copying the elements of the data contained within the ArrayList. That would mean, among other things, to do things like perform a clone() on the elements of the list, but not on the ArrayList (because that'll create a new cloned list with copies of the references to the same objects).
在不知道要存储/备份的数据类型是什么的情况下,很难准确说出如何解决您的问题,但请确保您正在复制 ArrayList 中包含的数据元素。这意味着,除其他外,执行诸如对列表元素执行 clone() 之类的操作,而不是在 ArrayList 上执行(因为这将创建一个新的克隆列表,其中包含对相同对象的引用的副本)。
回答by sblundy
All of these processes make shallow copies. If you're changing properties of objects with in the array, the two arrays have references to the same instance.
所有这些过程都会产生浅拷贝。如果您要更改数组中对象的属性,则这两个数组将引用同一个实例。
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()
will return "new val"
as well because org.get(0)
and copy.get(0)
return the exact same instance. You have to perform a deep copy like so:
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
}
回答by Paul Tomblin
Your question isn't very clear. If you clone() an ArrayList, the clone will not be modified if you change the contents of the original (ie if you add or remove elements) but it's a "shallow copy" so if you change the actual objects in the original they will also be changed in the clone.
你的问题不是很清楚。如果您 clone() 一个 ArrayList,如果您更改原始内容(即,如果添加或删除元素),则不会修改克隆,但它是“浅拷贝”,因此如果您更改原始中的实际对象,它们将也可以在克隆中进行更改。
If you want to make a "deep copy", so that changes to the actual objects will not affect the backups of them in the clone, then you need to create a new ArrayList and then go through the original one and for each element, clone it into the new one. As in
如果要进行“深度复制”,以便对实际对象的更改不会影响它们在克隆中的备份,则需要创建一个新的 ArrayList,然后遍历原始对象,并为每个元素克隆它进入新的。如
ArrayList backup = new ArrayList();
for (Object obj : data)
backup.add(obj.clone());
回答by Paul Brinkley
I'm assuming data
is the name of the ArrayList
you wanted to backup. If so, you should know that clone
is not deep- it only creates a copy of the object on which it is invoked, which in this case is the list. If it were a deep clone, it would fill the new list with clones of the objects in it.
我假设data
是ArrayList
您要备份的名称。如果是这样,您应该知道这clone
并不深- 它只创建调用它的对象的副本,在这种情况下是列表。如果它是一个深度克隆,它将用其中对象的克隆填充新列表。
Since it's not deep, if you change the objects the list contains, then the backup list will show those changes as well, since it's containing the same objects. The only time you'll not see changes in the backup after changing the "current" list is when you add or remove objects from the current list.
由于它不深,如果您更改列表包含的对象,那么备份列表也会显示这些更改,因为它包含相同的对象。更改“当前”列表后,您唯一不会在备份中看到更改的时间是在当前列表中添加或删除对象时。
Some classes may override clone
to be deep, but not all. In general, it's not something you can rely on. When creating a backup copy of Java collections, remember to either clone the contained objects as well, or deal only with collections of immutable objects.
某些类可能会覆盖clone
为深,但不是全部。一般来说,这不是你可以依赖的东西。创建 Java 集合的备份副本时,请记住也克隆包含的对象,或仅处理不可变对象的集合。
回答by Bill K
Regarding the cloning problem, once I solved this by serializing the entire collection into a string then serializing it back out into a new object. This forces you to make all your objects serializable and take when two objects really want to reference a single third object, but it can be a pretty good balance of simplicity and usefulness.
关于克隆问题,一旦我通过将整个集合序列化为一个字符串然后将其序列化为一个新对象来解决这个问题。这迫使您将所有对象序列化并在两个对象真正想要引用单个第三个对象时进行处理,但它可以在简单性和实用性之间取得很好的平衡。
Actually, I haven't tried this but you could probably use a pipe to serialize in and out at the same exact time so that you aren't storing 3 copies in memory (if it's a huge collection)
实际上,我还没有尝试过这个,但是您可能可以使用管道在同一时间序列化进出,这样您就不会在内存中存储 3 个副本(如果它是一个巨大的集合)
回答by PhiLho
I haven't tried it yet, but I think Collections.copy will do that.
我还没有尝试过,但我认为 Collections.copy 会做到这一点。
[EDIT] Now, I tried:
[编辑] 现在,我试过:
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);
}
回答by Tore A.
Depends what you need. Shallow copy (items in list are references to the same as in the original):
取决于你需要什么。浅拷贝(列表中的项目与原始项目相同):
ArrayList backup = new ArrayList(mylist.size());
backup.addAll(mylist);
Deep copy (items are copies also):
深拷贝(项目也是副本):
ArrayList backup = new ArrayList(mylist.size());
for(Object o : mylist) {
backup.add(o.clone());
}
回答by GunnarK
Here is a fully functioning ArrayList backup class that checks if the ArrayList already exists. Basically it's just a for-loop cycling through the list and manually adding them to the new list.
这是一个功能齐全的 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]
}
}