如何制作 ArrayList 的单独副本? [复制]
Posted
技术标签:
【中文标题】如何制作 ArrayList 的单独副本? [复制]【英文标题】:How to make a separated copy of an ArrayList? [duplicate] 【发布时间】:2010-11-22 18:01:17 【问题描述】:可能重复:Java: how to clone ArrayList but also clone its items?
我有一个如下示例程序:
ArrayList<Invoice> orginalInvoice = new ArrayList<Invoice>();
//add some items into it here
ArrayList<Invoice> copiedInvoice = new ArrayList<Invoice>();
copiedInvoice.addAll(orginalInvoice);
我想我可以修改copiedInvoice
中的项目,它不会影响originalInoice
中的这些项目。但是我错了。
如何制作ArrayList
的单独副本/克隆?
谢谢
【问题讨论】:
可能重复:***.com/questions/715650/… 正如 Zed 提到的那样。 我将其作为副本关闭,但不应将其删除。不是每个人都会知道使用原始使用的技术上更正确的“克隆”术语进行搜索。 【参考方案1】:是的,这是正确的 - 您需要实现 clone()
(或其他适合复制对象的机制,因为 clone()
被许多程序员认为是“损坏的”)。您的 clone()
方法应该对对象中的所有可变字段执行深层复制。这样,对克隆对象的修改不会影响原始对象。
在您的示例代码中,您将创建第二个ArrayList
并用对相同对象的引用 填充它,这就是为什么从List
s 都可以看到对象更改的原因。使用克隆方法,您的代码将如下所示:
List<Foo> originalList = ...;
// Create new List with same capacity as original (for efficiency).
List<Foo> copy = new ArrayList<Foo>(originalList.size());
for (Foo foo: originalList)
copy.add((Foo)foo.clone());
编辑:澄清一下,上面的代码正在执行原始List
的深拷贝,其中新的List
包含对原始对象副本的引用.这与调用ArrayList.clone()
形成对比,后者执行List
的shallow copy
。在这种情况下,浅拷贝会创建一个新的 List
实例,但包含对原始对象的引用。
【讨论】:
我认为如果您了解克隆列表与克隆列表中每个对象之间的区别,答案可能会更有帮助。但是,即使没有解释,答案也确实理解这一点,因此 +1 以补偿反对票。 错误:克隆在 java.lang.object 中具有“受保护”访问权限。 代码 sn-p 是基于 clone() 已在 Foo 类中被覆盖为公共的假设。【参考方案2】:如果您将可变对象存储到 ArrayList 中,则在复制 ArrayList 时需要复制每个对象。否则,新的 ArrayList 仍将保留原始引用。
但是,如果您要存储不可变对象,则可以使用:
ArrayList copiedInvoice = new ArrayList(originalInvoice);
【讨论】:
【参考方案3】:我认为我可以修改copyInvoice 中的项目,它不会影响originalInoice 中的这些项目。
发生这种情况是因为被复制的是引用变量而不是它自身的对象。
因此,您最终会得到两个指向同一个对象的“引用”。
如果您需要复制整个对象,您可能需要克隆它。
但是如果你不克隆对象的内部属性,如果它们碰巧是其他对象,你可能会遇到问题。
例如下面的类定义不会给你任何问题。
public class Something
private int x;
private int y;
private String stringObject;
如果您创建一个副本,您将复制其属性的当前值,仅此而已。
但是如果你的类里面确实有另一个对象,你也可以考虑克隆它。
class OtherSomething
Something something;
private int x;
如果您执行以下操作:
Something shared = new Something();
OtherSomething one = new OtherSomething();
OtherSomething two = new OtherSomething();
one.something = shared;
two.something = shared;
在这种情况下,一个和两个对相同的共享“某物”具有相同的引用变量,并且更改其中一个的值会影响另一个。
这就是为什么使用不可变对象更简单/更好/更容易的原因。
如果您需要更改不可变对象的值,您只需创建一个具有正确值的新对象。
【讨论】:
你说你分享你的第一堂课不会有问题:东西。但是,Date 是一个对象,更重要的是它是可变的,因此需要复制。 :P 不可变对象的错误选择.. 我为可变对象考虑了日期。谢谢亚当斯基【参考方案4】:看看 ByteArrayOutputStream 和 ByteArrayInputStream。如果您的所有类都实现了 Serializable,那么您可以使用上述类进行复制。
【讨论】:
以上是关于如何制作 ArrayList 的单独副本? [复制]的主要内容,如果未能解决你的问题,请参考以下文章