在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; }