据我了解,有几种方法(也许还有其他方法)在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();
}
答案 0 :(得分:105)
使用复制构造函数复制总是更好。 Java中的clone()
已被破坏(参见SO:How to properly override clone method?)。
Josh Bloch on Design - Copy Constructor versus Cloning
Bloch(顺便说一下,设计并实现了Collection框架)甚至更进一步说他只提供如果您已经阅读了我的书中有关克隆的内容,特别是如果您在这些内容之间进行了阅读,您会发现我认为
clone
已经被彻底打破了。 [...]Cloneable
被打破是一种耻辱,但它确实发生了。
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;
}