Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Shallow copy of a Map in Java

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(); } 
like image 313
dcp Avatar asked Mar 01 '10 15:03

dcp


People also ask

How will you create a shallow copy of a map?

To create a shallow copy of a Map , pass the existing Map as a parameter to the Map() constructor, e.g. const newMap = new Map(oldMap) . The Map() constructor takes an iterable, such as another Map , and adds the key-value pairs to the new Map .

What is the shallow copy in Java?

Shallow Copy/ Cloning Default implementation while using the clone() method a shallow copy of the object is created. It means it creates a new instance and copies all the fields of the object to that new instance where both are referencing to the same memory in heap memory.

How do I get a shallow copy of a HashMap instance?

HashMap clone() method. The best way to create shallow clone of hashmap is to use it's clone() method. It returns a shallow copy of the map. The keys and values themselves are not cloned; and point to same object in memory as in original map.


2 Answers

It's always better to copy using a copy constructor. clone() in Java is broken (see SO: How to properly override clone method?).

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.

like image 89
polygenelubricants Avatar answered Oct 03 '22 01:10

polygenelubricants


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); 
like image 40
Luca Fagioli Avatar answered Oct 03 '22 01:10

Luca Fagioli