Consider this. You have a list* of maps. You want to replicate the list a specified number of times. For example, if the list has two maps, and you want to create from this list another list that contains six maps. The constraint is that you have to write your own method, and you must not use Java’s object cloning feature.
The first approach is simple. You take each map in the list and add it to the list a specified number of times (n-1 times, if n is multiplier). If this is methodized, the code would look something like this.

A first-cut, defective solution
Basically, we add every map from the input list into a temporary list, and then add back to the original list each map “n” (or, in this case, “size”) number of times. And all is well.
Well? Think again. The above method will fail… miserably. It will, of course, return a list of maps that is n times bigger. But its utility ends there. If you work with the list, you will find that it behaves strangely. Modifying some element in the list will also modify some other element. Why does this happen?
In our ingenious first-cut method, we have add the same map multiple times to the list. What happens internally is that the list contains multiple references to the same map (or set of maps). So any change to one map in the resultant list will also modify all its replicas, since each map reference points to the same map. In essence, we have performed a shallow copy.
The correct approach (and I do not claim that this is the best) is to modify the map-copy portion of the above method (the second for-loop) as follows. Iterate through the map entries and copy each entry, i.e. key-value pair, to a temporary map, and when done, add this map to the list. This way, you are not left with references to a single map. Each map in the list is its own object.
Update
The purpose of the above was specifically to illustrate the concept of object references. The point is, you cannot copy objects in Java the way you copy simple data types. The more straightforward solution to the above (as Thejo points out) is to use the constructor of the HashMap (or another map implementation) class. Under the hood, however, the constructor does the same thing as we have done — it iterates through the map entries and copies each key-value pair of the passed map object to a new map object.
Here is how the method will look when refactored.
P.S.: Looking back, all this sounds very intuitive. Yet, intuition is not the first faculty that one can command when frantically debugging code on a Sunday evening.
* I have used list and map instead of List and Map. This is just for explanatory purposes. If you are a purist, please accept my sincerest apologies.
Related posts:
- Sloppy!Here’s what I found when signing up for a discounted copy of Windows 7 (for anyone with a .edu email...
- :))The only trouble in sharing a really good joke is having to explain it. ...
- So what?Saw this on the train ride home. I cannot comment on this advertisement without adding a standard disclaimer about “dignity...
- Adieu, PaoloThe greatest footballer the world never recognized as such. ...
Tags: Java, list, map, object cloning



May 12th, 2009 at 4:15 am
No need to iterate over the map to create a new one. Implementations of the Map interface provide a constructor to create a copy. That should be sufficient in your case as the key and value are strings. Not sure if it does a deep copy though.
May 12th, 2009 at 6:53 am
Thejo, you are right. I know of this constructor. The constructor does a deep copy. Actually, under the hood, the constructor does the same – it iterates over the map entries and copies key-value pairs to a new object.
The specific purpose of this post though was to illustrate object references… which is also why I had stated that this (the second-cut) was not the best . I’m updating the post with another refactored method.
May 12th, 2009 at 8:51 am
ayyo rama…enna ithu
May 12th, 2009 at 8:57 am
Quickly went through the source for HashMap. It seems to be a shallow copy. Makes sense too…
May 12th, 2009 at 10:34 am
@Selva: Summa dhaan. Technology has improved so much, you know!
@Thejo: I assume you meant a deep copy.
May 12th, 2009 at 12:43 pm
No….. I meant shallow copy. I don’t think any implementation in the Java API will guarantee a deep copy, as it is inherently dependent on your application. In your case, you can only be guaranteed deep copies if you have a map of primitives. Anything like,
HashMap mapCopy = new HashMap(myMap);
.. (where myMap is the same generic type as mapCopy, of course) can lead to the same references in the copy, based on the data in YourOwnComplexObject.
May 12th, 2009 at 12:47 pm
Ahhh… the generic type information was eaten up by Wordpress. Hope this one shows up correctly…
HashMap<String, YourOwnComplexObject> mapCopy = new HashMap<String, YourOwnComplexObject>(myMap);
May 12th, 2009 at 3:30 pm
Yes and no. I stand corrected in that Java does not guarantee deep copy. However,
Stringis technically not a primitive, yet you can get the compiler to deep-copy a map with String values.I assume the reason a shallow copy happens in the case of
YourOwnComplexObjectis because the Java compiler is unable to decode the getValue() method when iterating through the map entries. If this is so, one can get it to perform a deep copy by overriding thetoString()method. I haven’t tested it though.On second thoughts, I don’t think even that would help. We might need some sort of recursive reflection built into getValue() to achieve deep copy.
June 2nd, 2009 at 12:04 pm
Hi, String is immutable so any copy will be a deep one, cause if use another String it has another object ref.
So it isn’t a good a example for copying Maps.
If you want to get a deep copy you have to iterate and to call a proper implemented clone-method or something like that.
See “Effective Java 2nd Ed. Item 11″. A very good and useful book, by the way.
What I was looking for, as I had found this blog, was how to copy a map which uses wildcards like Map<? extends Enum, ? extends TB_BasicData>. Coping itself not a real problem, but creating a new map of the same types is the problem.
Code form java.util.HashMap
public HashMap(Map m) {
this(Math.max((int) (m.size() / DEFAULT_LOAD_FACTOR) + 1,
DEFAULT_INITIAL_CAPACITY), DEFAULT_LOAD_FACTOR);
putAllForCreate(m);
}
private void putAllForCreate(Map m) {
for (Iterator<? extends Map.Entry> i = m.entrySet().iterator(); i.hasNext(); ) {
Map.Entry e = i.next();
putForCreate(e.getKey(), e.getValue());
}
}
...
“putForCreate” omitted here, but makes no difference.
So it is clear that it makes no deep copy and iterates over the old map.
Greetings Michael
June 3rd, 2009 at 10:25 am
Hi,
about coping “Map”,
I had to be more restrictive and parametrized it more:
public class TB_NodeData<K extends Enum, V extends TB_BasicData> extends TB_BasicData {
private Map subMap;
public TB_NodeData(final TB_NodeData source) {
super(source);
this.subMap = new EnumMap(source.subMap);
if (this.subMap != null) {
for (final Map.Entry entry : this.subMap.entrySet()) {
entry.setValue((V) entry.getValue().copy());
}
}
}
copy is my implementation of a my own deep copy, cause it didn’t like the restrictions of clone() contract.
So it is no problem any more.