【问题标题】:How to make a separated copy of an ArrayList? [duplicate]如何制作 ArrayList 的单独副本? [复制]
【发布时间】: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 的单独副本/克隆?

谢谢

【问题讨论】:

  • 可能重复:stackoverflow.com/questions/715650/… 正如 Zed 提到的那样。
  • 我将其作为副本关闭,但不应将其删除。不是每个人都会知道使用原始使用的技术上更正确的“克隆”术语进行搜索。

标签: java arraylist clone


【解决方案1】:

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

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

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() 形成对比,后者执行Listshallow 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,那么您可以使用上述类进行复制。

    【讨论】:

      猜你喜欢
      • 2011-10-25
      • 2017-06-23
      • 2018-10-08
      • 2018-08-25
      • 1970-01-01
      • 2011-03-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多