简体   繁体   中英

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?

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.

No they are not. Generics are not covariant in Java.

If they are covariant you can logically put any type of List instead of ArrayList which defeats the purpose of having generics.

Consider reading Effective Java (2nd Edition) Chapter 5: Generics which has very good explanation of Generics.

Another good read is http://www.angelikalanger.com/GenericsFAQ/JavaGenericsFAQ.html

Ask yourself a question if you need particular list implementation in your Map or any List? In case of particular implementation you can use your last example:

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

In case of any list just use:

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

BTW the second option usually is better from design point of view so if you don't know exactly for now - try using second option first.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM