问题

据我所知,有几种方法(也许还有其他方法)可以在Java中创建aMap的浅表副本:

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();

一种方式优于另一种方式,如果是这样,为什么?

值得一提的是,第二种方式是"Unchecked Cast"警告。所以你必须添加@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();
}

#1 热门回答(104 赞)

使用复制构造函数复制总是更好.344478101在Java中被破坏(参见SO:How to properly override clone method?)。
Josh Bloch on Design - Copy Constructor versus Cloning>如果你已经阅读了我书中关于克隆的项目,特别是如果你在这两行之间阅读,你会知道我认为克隆已经深受打击。 [...] Cloneable被打破是一种耻辱,但它确实发生了。

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

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


#2 热门回答(54 赞)

无论是两个:theconstructorthat你是指为aMap theHashMapimplementation,被定义(以及其他人),但不是Map接口本身(例如,考虑Map接口的theProviderimplementation:你会不会发现,构造函数)。

另一方面,不建议使用23508570方法,正如Josh Bloch所解释的那样。

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

将指定映射中的所有映射复制到此映射(可选操作)。对于在指定映射中从键k到值v的每个映射,此调用的效果等效于在此映射上调用put(k,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);

#3 热门回答(10 赞)

复制 Map 而不知道其实现:

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

原文链接