从Java Map <string,object =“”> propertyMap </string,>添加*副本*条目

时间:2012-09-11 17:07:31

标签: java collections immutability defensive-programming

我想将propertyMap的副本添加到我的propertyMap:

  public void addProperties(Map<String, Object> propertyMap) {
    for (Map.Entry<String, Object> propertyEntry : propertyMap.entrySet()) {
      this.propertyMap.put(propertyEntry.getKey(), propertyEntry.getValue());
    }
  }

上面的代码没有这样做,但希望传达意图?

最好的方法是什么?我做过一些关于“克隆”,“防御性复制”,“不可变对象”,Collections.unmodifiable ......之类的阅读,但我比以前更加困惑。

我需要的是,在典型的SO风格中,请更好地在代码片段中写出我的意思。

2 个答案:

答案 0 :(得分:3)

看起来你可以使用putAll

public void addProperties(Map<String, Object> propertyMap) {
    this.propertyMap.putAll(propertyMap);
}

这称为“防御性复制”。这里发生的是本地propertyMap中的值被复制到实例的propertyMap中。这里的一个弱点是,给定propertyMap的更改不会反映在实例的propertyMap中。这实质上是创建给定地图的快照并将该快照复制到实例字段地图。

还有其他方法可以创建防御性副本,包括clone()HashMap(Map)构造函数。

对于不可变集合,Collections中的不可修改方法将返回在您尝试添加异常时抛出异常的集合。例如,

Set<String> strs = Collections.unmodifiableSet(new HashSet<String>());
strs.add("Error"); // This line throws an exception

不可变集合通过禁止修改(删除和添加)来保护其值,而防御副本通过不引用复制的集合来保护其值(换句话说,原始集合中的更改未显示在副本中)。

答案 1 :(得分:1)

我认为对于每个键,您不必担心复制,因为它们是不可变的。但对于值,它取决于它们是什么类型的对象。如果它们是可变对象,那么你必须复制所有这些对象。

public void addProperties(Map<String, Object> propertyMap) { 
    Cloner cloner = new Cloner();
    for (Map.Entry<String, Object> propertyEntry : propertyMap.entrySet()) { 
        this.propertyMap.put(propertyEntry.getKey(), cloner.deepClone(propertyEntry.getValue())); 
    } 
} 

您可以检查此内容以进行深层克隆Deep clone utility recomendation

从主页http://code.google.com/p/cloning/

  

重要提示:深度克隆Java类可能意味着克隆了数千个对象!克隆文件和流可能会导致JVM崩溃。为了查看克隆的内容,强烈建议在开发期间将克隆类转储到stdout。

所以,知道你要克隆的东西很好。