在Java中的地图的浅色副本

据我所知,有几种方法(也许还有其他的方法)可以创build一个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(); 

其中一种方法比另一种更好,如果是这样,为什么?

有一点值得一提的是,第二种方式给出了一个“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(); } 

使用复制构造函数复制总是更好。 Java中的clone()被破坏(请参阅SO: 如何正确覆盖clone方法? )。

乔希布洛赫在devise – 复制构造与克隆

如果你已经阅读了我书中关于克隆的内容,特别是如果你在各行之间阅读,你会知道我认为clone已经被深深地打破了。 Cloneable被破解是一件Cloneable事情,但事实恰恰如此。

布洛赫(顺便说一句,devise并实现了Collection框架)甚至进一步说,他只是提供clone()方法,就是“因为人们期望它”。 他根本不推荐使用它。


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

这两者都不是:你所指的构造函数是为Map的HashMap实现定义的,而不是为Map接口本身定义的(例如,考虑Map接口的Provider实现:将不会find该构造函数)。

另一方面,使用clone()方法是不可取的,正如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); 

复制地图而不知道它的实现:

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