【问题标题】:Clone collection containing another collection克隆包含另一个集合的集合
【发布时间】:2014-12-18 21:10:22
【问题描述】:

我有一个类,其中包含一个集合字段(宠物)。该字段包含其他集合,这些集合又包含对象。我想创建此类对象之一的深层副本。

我读过关于使用复制构造函数的文章,这似乎比使用 Cloneable 接口更舒服。我在我的 Person 类中实现了一个,并使用了 ArrayList 的复制构造函数。不幸的是,pets ArrayList 的副本不是 deepcopy - 内容仍然引用相同的内容。只有 pets ArrayList 本身被复制。 所以构造函数 ArrayList(Collection c) 没有做我想做的事。但我也读过关于遍历集合以再次复制其内容的信息——这就是我在下面的示例中所做的。 到这里,pets ArrayList 和内容,包含不同动物的 ArrayLists 被克隆。

但是动物列表中的动物对象呢? John 和 JohnClone 有自己的宠物列表,但宠物还是一样的。如果约翰的狗奥丁发生了什么事,约翰克隆的狗仍然会受到影响。

我错过了什么?如何创建集合的真正深层副本?

public class Person {

String name;
int age;
ArrayList pets;

public Person(String name, int age, ArrayList pets) {
    this.name = name;
    this.age = age;
    this.pets = pets;
}

public Person(Person person) {
    name = person.name;
    age = person.age;

    // pets = ArrayList(person.pets) didn't copy its contents
    ArrayList clone = new ArrayList();
    for (Object list : person.pets) { 
        clone.add(new ArrayList((ArrayList) list));
    }
    pets = clone;
}

public static void main(String[] args) throws Exception {

    ArrayList dogs = new ArrayList();
    dogs.add(new Dog("Odin"));
    dogs.add(new Dog("Hachiko"));

    ArrayList cats = new ArrayList();
    cats.add(new Cat("Whisky"));

    ArrayList johnsPets = new ArrayList();
    johnsPets.add(dogs);
    johnsPets.add(cats);

    Person john = new Person("John Doe", 33, johnsPets);
    Person johnClone = new Person(john);
}

我将 Person 的字段保留为默认值,并且没有在集合中使用泛型以避免不必要地膨胀这个简短的示例。

【问题讨论】:

  • 显然,您必须手动确保您克隆一直向下

标签: java copy clone copy-constructor deep-copy


【解决方案1】:

我想我会坚持使用类似于 Suresh Sajja 提到的用于克隆嵌套不太深的对象的解决方案。

否则我阅读了有关序列化对象以创建深层副本的信息:Deep cloning objects。 我想这些是必须使用的解决方案,因为 Java 没有提供这样的方法。

【讨论】:

    【解决方案2】:

    执行与在宠物中克隆动物列表相同的方法。用对象的克隆构造数组列表

    ArrayList clone = new ArrayList();
    for (Object list : person.pets) {
        ArrayList objClone = new ArrayList();
         for(Object obj : list){
          objClone.add(obj.clone()); //you have to honour the contract of cloneable while doing this on dog, cat objects
        }
        clone.add(objclone);
    }
    pets = clone;
    

    【讨论】:

    • 我尝试了您的解决方案,但我不得不对其进行一些修改。起初我想避免使用 Cloneable,所以我在 Dog 和 Cat 中添加了一个复制构造函数。我必须使用 instanceof 来决定我必须创建哪种动物。总而言之,sn-p 工作正常。但是这个解决方案要求我确切地知道我的集合嵌套的深度。此外,当可能有比狗和猫更多的动物时,我将不得不使用许多 instanceof。回到 Cloneable:您是否有理由要使用 obj.clone() 而不是为狗和猫提供复制构造函数?
    • 为了避免instanceof检查,你必须开始使用泛型
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-22
    • 2011-06-02
    • 1970-01-01
    • 2018-12-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多