克隆集合包含另一个集合

时间:2014-10-23 08:26:06

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

我有一个类,其中包含一个收集字段(宠物)。该字段包含其他集合,这些集合再次包含对象。我想创建一个这个类的对象的深度复制。

我已经阅读过有关使用复制构造函数的内容,这看起来比使用Cloneable接口更舒服。我在Person类中实现了一个并使用了ArrayList的复制构造函数。不幸的是,宠物ArrayList的副本不是深度复制 - 内容仍然引用相同的内容。只复制了宠物ArrayList本身。 所以构造函数 ArrayList(Collection c)没有按照我的意愿去做。但我也读过关于迭代集合以再次复制其内容的内容 - 这就是我在下面的例子中所做的。 在这里克隆了宠物ArrayList和内容,包含不同动物的ArrayLists。

但动物名单中的动物物品怎么样? John和JohnClone有他们自己的宠物清单,但宠物仍然是一样的。如果John的狗Odin发生了什么事,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的字段默认值,并且没有在集合中使用泛型,这不是不必要的膨胀这个简短的例子。

2 个答案:

答案 0 :(得分:1)

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

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

答案 1 :(得分:0)

以与在宠物中克隆动物名单相同的方式行事。使用Objects

的克隆构造数组列表
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;