Shallow copy of a Map in Java

JavaMapCloneShallow Copy

Java Problem Overview


As I understand it, there are a couple of ways (maybe others as well) to create a shallow copy of a Map in Java:

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

Is one way preferred over the other, and if so, why?

One thing worth mentioning is that the second way gives an "Unchecked Cast" warning. So you have to add @SuppressWarnings("unchecked") to get around it, which is a little irritating (see below).

@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 Solutions


Solution 1 - Java

It's always better to copy using a copy constructor. clone() in Java is broken (see SO: https://stackoverflow.com/questions/2326758/how-to-properly-override-clone-method/2326801#2326801">How to properly override clone method?).

http://www.artima.com/intv/bloch13.html">Josh Bloch on Design - Copy Constructor versus Cloning

> If you've read the item about cloning in my book, especially if you read between the lines, you will know that I think clone is deeply broken. [...] It's a shame that Cloneable is broken, but it happens.

Bloch (who by the way, designed and implemented the Collection framework) even went further in saying that he only provides the clone() method just "because people expect it". He does NOT actually recommend using it at all.


I think the more interesting debate is whether a copy constructor is better than a copy factory, but that's a different discussion altogether.

Solution 2 - Java

Neither of the two: the constructor that you are referring to is defined for the HashMap implementation of a Map, (as well as for others) but not for the Map interface itself (for example, consider the Provider implementation of the Map interface: you will not find that constructor).

On the other hand it is not advisable to use the clone() method, as explained by Josh Bloch.

In respect of the Map interface (and of your question, in which you ask how to copy a Map, not a HashMap), you should use Map#putAll():

> Copies all of the mappings from the specified map to this map > (optional operation). The effect of this call is equivalent to that of > calling put(k, v) on this map once for each mapping from key k to > value v in the specified map.

Example:

// 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);

Solution 3 - Java

Copy a map without knowing its implementation:

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestiondcpView Question on Stackoverflow
Solution 1 - JavapolygenelubricantsView Answer on Stackoverflow
Solution 2 - JavaLuca FagioliView Answer on Stackoverflow
Solution 3 - JavaTerrisView Answer on Stackoverflow