java 中的集合深度克隆

Deep Cloning of Collections in java

最近我在面试中遇到了这个问题:

编写函数 return class 绘图的深层克隆实例

public class Drawing{

  public List<Shape> shapes=new LinkedList<Shape>();

}

其中 shape 是一个抽象的 class 有很多具体的实现

public abstract class Shape implements Serializable{

}

谁能告诉我如何解决这个问题?我们是否需要在所有具体实现中添加克隆方法?

Shape 的每个子 class 都知道如何创建自己的深拷贝,因为这是 Serializable 实现应该做的一件事。因此,在 Drawing 和 serialize/deserialize 中迭代 Shape 对象中的列表,以创建列表中每个 Shape 的深层副本。

您还可以 use a library 比序列化方法更快。

Cloner cloner=new Cloner();

MyClass clone=cloner.deepClone(o);
// clone is a deep-clone of o

我建议使用 Apach Commons Lang 中的 SerializationUtils.clone

此方法用于深度克隆:

SomeObject cloned = org.apache.commons.lang.SerializationUtils.clone(someObject);

这是一种克隆对象的简单方法,但如果您追求性能,则不行。

See documentation

您需要做的是首先序列化 List<Shape>,然后反序列化 return Drawing 的新实例,反序列化 List

public static Drawing deepClone(Drawing drawing) {
    try {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(baos);
        oos.writeObject(drawing.shapes); //Serializes the drawing.shapes

        ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
        ObjectInputStream ois = new ObjectInputStream(bais); 
        return new Drawing((LinkedList<Shape>)ois.readObject()); //Deserializing and reading 
    } catch (IOException e) {
        return null;
    } catch (ClassNotFoundException e) {
        return null;
    }
}

假设您在 Drawing 中有一个构造函数,它接受一个 LinkedList<Shape> 作为参数

编辑

实现 Cloneable 接口时覆盖 clone() 方法,因此不需要在 Shape class 中添加 clone(),但根据问题,他们希望您使用 Serializable 界面创建克隆。