在Java中的地图的浅拷贝

时间:2010-03-01 15:23:54

标签: java map clone shallow-copy

据我了解,有几种方法(也许还有其他方法)在Java中创建Map的浅表副本:

Map<String, Object> data = new HashMap<String, Object>();
Map<String, Object> shallowCopy;

// first way
shallowCopy = new HashMap<String, Object>(data);

// second way
shallowCopy = (Map<String, Object>) ((HashMap<String, Object>) data).clone();

一种方式比另一方更受欢迎,如果是,为什么?

值得一提的是,第二种方式是“未经检查的投射”警告。所以你必须添加@SuppressWarnings("unchecked")来解决它,这有点令人恼火(见下文)。

@SuppressWarnings("unchecked")
public Map<String, Object> getDataAsMap() {
    // return a shallow copy of the data map
    return (Map<String, Object>) ((HashMap<String, Object>) data).clone();
}

3 个答案:

答案 0 :(得分:105)

使用复制构造函数复制总是更好。 Java中的clone()已被破坏(参见SO:How to properly override clone method?)。

Josh Bloch on Design - Copy Constructor versus Cloning

  

如果您已经阅读了我的书中有关克隆的内容,特别是如果您在这些内容之间进行了阅读,您会发现我认为clone已经被彻底打破了。 [...] Cloneable被打破是一种耻辱,但它确实发生了。

Bloch(顺便说一下,设计并实现了Collection框架)甚至更进一步说他只提供clone()方法,因为人们期待它“。他实际上并不建议使用它。


我认为更有趣的争论是复制构造函数是否比复制工厂更好,但这完全是一个不同的讨论。

答案 1 :(得分:56)

两者都不是:您所指的constructor是为HashMap(以及其他人)的Map实现而定义的,而不是针对Map接口的本身(例如,考虑Map接口的Provider实现:您将找不到该构造函数)。

另一方面,不建议使用clone()方法,如Josh Bloch所解释。

关于Map界面(以及你问的如何复制Map而不是HashMap的问题),你应该使用Map#putAll()

  

将指定地图中的所有映射复制到此地图   (可选操作)。此调用的效果等同于   对于从k到k的每个映射,在此映射上调用put(k,v)一次   指定地图中的值v。

示例:

// HashMap here, but it works for every implementation of the Map interface
Map<String, Object> data = new HashMap<String, Object>();
Map<String, Object> shallowCopy = new HashMap<String, Object>();

shallowCopy.putAll(data);

答案 2 :(得分:11)

复制地图而不知道其实施:

static final Map shallowCopy(final Map source) throws Exception {
    final Map newMap = source.getClass().newInstance();
    newMap.putAll(source);
    return newMap;
}