如何制作ArrayList的分离副本?

可能重复:
Java:如何克隆ArrayList但是也克隆了它的项目?

我有一个示例程序,如下所示:

ArrayList orginalInvoice = new ArrayList(); //add some items into it here ArrayList copiedInvoice = new ArrayList(); copiedInvoice.addAll(orginalInvoice); 

我以为我可以修改copiedInvoice项目,它不会影响originalInoice这些项目。 但是我错了。

如何对ArrayList进行单独的复制/克隆?

谢谢

是的,这是正确的 – 您需要实现clone() (或其他合适的机制来复制您的对象,因为clone()被许多程序员认为是“破坏”。 clone()方法应该对对象中的所有可变字段执行深层复制。 这样,对克隆对象的修改不会影响原始对象。

在您的示例代码中,您正在创建第二个ArrayList并使用对相同对象的引用来填充它,这就是为什么从List中可以看到对象的更改。 使用克隆方法,您的代码将如下所示:

 List originalList = ...; // Create new List with same capacity as original (for efficiency). List copy = new ArrayList(originalList.size()); for (Foo foo: originalList) { copy.add((Foo)foo.clone()); } 

编辑 :为了澄清,上面的代码正在执行原始List深层副本 ,其中新List包含对原始对象的副本的引用。 这与调用ArrayList.clone()形成对比,后者执行Listshallow copy 。 在此上下文中,浅复制创建一个新的List实例,但包含对原始对象的引用。

如果要将可变对象存储到ArrayList中,则需要在复制ArrayList时复制每个对象。 否则,新的ArrayList仍将保留原始引用。

但是,如果您正在存储不可变对象,则可以使用:

ArrayList copiedInvoice = new ArrayList(originalInvoice);

我以为我可以修改copiedInvoice中的项目,它不会影响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; 

在这种情况下,一个和两个具有相同的共享“某物”的相同参考变量,并且改变一个中的值将影响另一个。

这就是使用不可变对象更简单/更好/更容易的原因。

如果需要更改不可变对象的值,只需创建一个具有正确值的新值即可。

看看ByteArrayOutputStream和ByteArrayInputStream。 如果所有类都实现了Serializable,那么您可以使用上面提到的类进行复制。