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.
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.
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.
No related posts.