2

I have a very simple code to populate hashmap with arrayList. Following is the code snippet

HashMap<String, ArrayList<String> > fieldValue = new HashMap<String, ArrayList<String>>();
ArrayList<String> tmp = new ArrayList<>();

tmp.add("f");
tmp.add("string");
tmp.add("false");
fieldValue.put("bas", tmp);

tmp.clear();
tmp.add("f");
tmp.add("string");
tmp.add("false");
fieldValue.put("usc", tmp);

tmp.clear();
tmp.add("f");
tmp.add("int");
tmp.add("false");
fieldValue.put("st", tmp);

for (Map.Entry r : fieldValue.entrySet()) {
    System.out.println(r.getKey() + "\t" + r.getValue());
}

Following is the output when I execute it

st  [f, int, false]
usc [f, int, false]
bas [f, int, false]

Where is the problem? I was expecting there different values in hashmap value but they are all same. Am I missing something?

Zabuzard
  • 25,064
  • 8
  • 58
  • 82
Hafiz Muhammad Shafiq
  • 8,168
  • 12
  • 63
  • 121
  • 5
    The problem is: you're putting the _same_ list `tmp` as the value for different keys and change the list before doing so. Instead of `tmp.clear();` do `tmp = new ArrayList<>();` and it should be fine. - Note that lists are _not_ immutable (if they were there would be no `clear()`). – Thomas Aug 08 '18 at 13:12
  • how do I do this ? I expect value of tmp should be in hashmap before I clear it for next record – Hafiz Muhammad Shafiq Aug 08 '18 at 13:13
  • " I expect value of tmp should be in hashmap before I clear it for next record" - that's wrong thinking. What you put into the hashmap is a _reference_ to the list, not a copy. Hence calling `put()` 3 times with the same instance causes the same instance to be in the map 3 times - not 3 copies. – Thomas Aug 08 '18 at 13:14
  • Possibly related: [Why does my ArrayList contain N copies of the last item added to the list?](https://stackoverflow.com/q/19843506) – Pshemo Aug 08 '18 at 13:16
  • In contrast to other languages, Java does **not** copy your list when you pass it to a method. Java only passes the *reference* to the instance (this is called *pass-by-value*). The instance itself is still the same. So your variable `tmp` links to the same list that is saved inside the map. – Zabuzard Aug 08 '18 at 13:28
  • You really want to read about pass by value vs pass by reference and such things. – GhostCat Aug 08 '18 at 13:38

2 Answers2

2

The code

fieldValue.put(..., tmp);

does not clone the list tmp, it just puts into the map as a value the reference to the list.

So finally you have in the map the last content of the list.

You should not recycle the tmp variable, but you should always create a new independent list.

Honza Zidek
  • 9,204
  • 4
  • 72
  • 118
1

tmp.clear(); Just only removes data from the collection. But you still put the same object tmp for different keys. As it said above, you have to create a new collection new ArrayList(tmp).

dehasi
  • 2,644
  • 1
  • 19
  • 31