在里面用List初始化Map

时间:2013-09-19 06:31:09

标签: java

我需要使用带有List的Map:

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

我在eclipse中遇到编译错误。

唯一可行的工作似乎是将Map中的内部List更改为ArrayList

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

我不得不改变许多接口方法的签名,但我仍然没有得到它;为什么第一个定义不起作用?

是不是一样,不应该

Map<String, List<String>> keyToGroup 

&安培;

Map<String, ArrayList<String>>

是一样的吗?

3 个答案:

答案 0 :(得分:8)

不,他们不是。考虑一下:

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

第二行没问题,因为LinkedList<String>List<String> - 但在将HashMap<String, ArrayList<String>>添加到LinkedList<String>方面,它在逻辑上并不合适,因为ArrayList<String> 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

更清楚:

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

这不仅仅是集合作为类型参数的情况。使用正常继承看起来更简单:

{{1}}

即使每个香蕉都是水果,所以“香蕉的集合”是“收集水果*”,意思是取出它们,而不是每种香蕉都是香蕉。

在某些情况下,您可以使用wildcard parameterized types来提供帮助,但这取决于您要实现的目标。

答案 1 :(得分:0)

不,他们不是。泛型在Java中不是协变

如果它们是协变的,你可以在逻辑上放置任何类型的List而不是ArrayList,这会违背仿制药的目的。

考虑阅读Effective Java(第2版)第5章:泛型,它对泛型有非常好的解释。

另一个好的读物是http://www.angelikalanger.com/GenericsFAQ/JavaGenericsFAQ.html

答案 2 :(得分:0)

如果您需要在地图或任何列表中使用特定列表,请问自己一个问题? 如果是特定实现,您可以使用上一个示例:

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

如果有任何列表,请使用:

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

BTW第二个选项通常从设计的角度来看更好,所以如果你现在还不知道 - 请先尝试使用第二个选项。