Trouble with Map iterate

I want to iterate Map, where the value is another Map. I have this method:

 public void test(){
   Map<Integer, Double> map1 = new HashMap<Integer, Double>();
   Map<Integer, Map<Integer, Double>> map2 = new HashMap<Integer, Map<Integer, Double>>();
   map1.put(1,1.1);
   map1.put(2,2.2);
   map1.put(3,3.3);
   map2.put(1,map1);
   map1.clear();
   map1.put(4,4.4);
   map1.put(5,5.5);
   map1.put(6,6.6);
   map2.put(2,map1);

   for (Map.Entry<Integer, Map<Integer, Double>> entry : map2.entrySet()){
       Log.d("test", "map2 key " + entry.getKey());
       Map<Integer, Double> tempMap = new HashMap<Integer, Double>(entry.getValue());
       for (Map.Entry<Integer, Double> entry1 : tempMap.entrySet()){
           Log.d("map", "map1 key " + entry1.getKey() + "map1 value " + entry1.getValue());
       }
   }

And I see in logs this:

map2 key 1
map1 key 4 map1 value 4.4
map1 key 5 map1 value 5.5
map1 key 6 map1 value 6.6
map2 key 2
map1 key 4 map1 value 4.4
map1 key 5 map1 value 5.5
map1 key 6 map1 value 6.6

What's the problem?

Jon Skeet
people
quotationmark

What's the problem?

You've put the same value in the "outer" map for both entries: a reference to the single Map<Integer, Double> you've created. When you call put, it just adds the reference to the map - it doesn't take a deep copy of the object at that point and store a reference to the copy.

If you want two separate maps, you need to create them explicitly:

Map<Integer, Double> inner1 = new HashMap<Integer, Double>();
inner1.put(1,1.1);
inner1.put(2,2.2);
inner1.put(3,3.3);
Map<Integer, Double> inner2 = new HashMap<Integer, Double>();
inner2.put(4,4.4);
inner2.put(5,5.5);
inner2.put(6,6.6);

Map<Integer, Map<Integer, Double>> outer = new HashMap<Integer, Map<Integer, Double>>();
outer.put(1, inner1);
outer.put(2, inner2);

(You don't have to use two different variables here, but I find it helpful.)

It's very important that you understand the difference between references and objects in Java - the value of a variable is never, ever an object... it's always either a primitive or a reference. So if you write something like:

StringBuilder builder1 = new StringBuilder();
StringBuilder builder2 = builder1;
builder2.append("foo");
System.out.println(builder1);

... it will print out "foo" because you've only got a single StringBuilder, with two variables that happen to both have references to the same object.

people

See more on this question at Stackoverflow