Question

I would like to add copies of a propertyMap to my propertyMap:

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

The code above does not do that but hopefully conveys the intent?

What's the best way to do this? I have done some reading on "cloning", "defensive copying", "immutable objects", Collections.unmodifiable... and the like but I am more confused than before.

All I need, in typical SO style, is a better way to write what I mean in the code snippet, please.

Was it helpful?

Solution

It looks like you can just use putAll:

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

This is called "defensive copying". What happens here is the values in the local propertyMap are copied into the instance's propertyMap. A weakness here is that changes the given propertyMap aren't going to be reflected in the instance's propertyMap. This is essentially creating a snapshot of the given map and copying that snapshot to the instance field map.

There are other ways of creating defensive copies as well, including clone() and the HashMap(Map) constructor.

For immutable collections, the unmodifiable methods in Collections will return collections that throw exceptions when you try to add to them. For example,

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

Immutable collections protect their values by disallowing modification (removing and adding) while defensive copies protect their values by not referencing the copied collection (in other words, changes in the original collection aren't shown in the copy).

OTHER TIPS

I think for each key you don't have to worry about making copies because they are immutable. But for the values it depends on what type objects they are. If they are mutable objects then you have to make copies of all of them.

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

You can check this for deep clonning Deep clone utility recomendation.

From the homepage http://code.google.com/p/cloning/

IMPORTANT : deep cloning of Java classes might mean thousands of objects are cloned! Also cloning of files and streams might make the JVM crash. Enable dumping of cloned classes to stdout during development is highly recommended in order to view what is cloned.

So, it's good to know what you are trying to clone.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top