【问题标题】:Deep Cloning of Collections in java [closed]java中集合的深度克隆[关闭]
【发布时间】:2015-07-16 11:12:06
【问题描述】:

最近我在一次采访中遇到了这个问题:

编写一个函数以返回绘图类的深层克隆实例

public class Drawing{

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

}

其中 shape 是一个具有许多具体实现的抽象类

public abstract class Shape implements Serializable{

}

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

【问题讨论】:

  • Shape 实现 Serializable 的事实是一个提示。面试官可能只是希望你序列化 List 并反序列化它,并创建一个引用反序列化列表的新绘图实例。
  • @JBNizet 另一方面,如果 Shape 有瞬态字段,它们会在序列化过程中丢失,但如果对象被克隆则不会丢失。
  • 检查这是否有帮助 stackoverflow.com/questions/64036/…

标签: java cloning


【解决方案1】:

你需要做的是首先序列化List&lt;Shape&gt;,然后反序列化并返回一个新的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;
    }
}

假设您在绘图中有一个以LinkedList&lt;Shape&gt; 作为参数的构造函数

编辑

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

【讨论】:

  • 这是一个很好的答案,但是我认为它应该说明transient 子类的transient 字段,如果有的话。在这种情况下,深度克隆将不适用于这些领域。我的意思是,就像在面试问题中那样,也许 OP 应该提到这一点,并明确表示这是要付出的代价。
【解决方案2】:

Shape 的每个子类都知道如何创建自己的深层副本,因为这是Serializable 实现应该做的一件事。所以迭代Drawing 中的列表并序列化/反序列化Shape 对象以创建列表中每个Shape 的深层副本。

【讨论】:

  • 为什么要遍历列表并一一序列化Shapes? LinkedList也是Serializable,所以对列表进行序列化和反序列化就足够了。
【解决方案3】:

您也可以use a library,这比序列化方法更快。

Cloner cloner=new Cloner();

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

【讨论】:

  • 我认为他需要知道如何使用 Serializable 而不是使用库,因为这是一个面试问题,他不能在面试中直接说库。
  • 为什么不呢?我认为建议使用图书馆很聪明。 OP只需要真正了解他选择它的原因(即序列化方法如何工作)
【解决方案4】:

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

此方法用于深度克隆:

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

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

See documentation

【讨论】:

  • 这不是一个答案...请解释你为什么建议,使用它的好处和缺点。甚至可能显示一些示例代码
  • 刚刚编辑了我的答案
猜你喜欢
  • 1970-01-01
  • 2012-02-26
  • 1970-01-01
  • 1970-01-01
  • 2017-09-17
  • 2010-10-14
  • 2017-07-12
  • 2011-08-13
相关资源
最近更新 更多