Initializing a Map with List inside

I need to use a Map with a List inside :

Map<String, List<String>> keyToGroup = new HashMap<String, ArrayList<String>>();

I am getting compiler error on this line in eclipse.

The only working thing seem to be changing the inside List in the Map to ArrayList

Map<String, ArrayList<String>> keyToGroup = new HashMap<String, ArrayList<String>>();

I had to change the signature of many interfaces' methods, but I still don't get it; why isn't the first definition work?

Isn't it the same, should not

Map<String, List<String>> keyToGroup 

&

Map<String, ArrayList<String>>

be the same?

Jon Skeet
people
quotationmark

No, they're not. Consider this:

Map<String, List<String>> keyToGroup = new HashMap<String, ArrayList<String>>();
keyToGroup.put("foo", new LinkedList<String>());

The second line is fine, because a LinkedList<String> is a List<String> - but it's not logically fine in terms of adding it to a HashMap<String, ArrayList<String>>, because a LinkedList<String> is not an ArrayList<String>.

To make it clearer:

Map<String, ArrayList<String>> map1 = new HashMap<String, ArrayList<String>>();
Map<String, List<String>> map2 = map1; // This is invalid
map2.put("foo", new LinkedList<String>());
ArrayList<String> oops = map1.get("foo"); // Because this would be broken

This isn't just the case with collections as the type argument. It's even simpler to see with normal inheritance:

List<Banana> bunchOfBananas = new ArrayList<Banana>();
List<Fruit> fruitBowl = bunchOfBananas; // Invalid!
fruitBowl.add(new Apple());
Banana banana = bunchOfBananas.get(0);

Even though every banana is a fruit, so a "collection of bananas" is a "collection of fruit* in the sense of fetching them, not every fruit is a banana.

You can use wildcard parameterized types to help in some cases, but it depends on exactly what you're trying to achieve.

people

See more on this question at Stackoverflow