在里面用List初始化Map

我需要使用带有List的Map:

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

我在eclipse中遇到编译错误。

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

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

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

是不是一样,不应该

 Map<String, List> keyToGroup 

 Map<String, ArrayList> 

是相同的?

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

 Map> keyToGroup = new HashMap>(); keyToGroup.put("foo", new LinkedList()); 

第二行很好,因为LinkedList是一个List – 但是在将它添加到HashMap>方面它在逻辑上并不合适,因为LinkedList 不是 ArrayList

为了更清楚:

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

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

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

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

在某些情况下,您可以使用通配符参数化类型来帮助,但这取决于您要实现的目标。

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

 Map> keyToGroup = new HashMap>(); 

如果有任何列表只需使用:

 Map> keyToGroup = new HashMap>(); keyToGroup.put("arraylist", new ArrayList 

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

不,他们不是。 generics在Java中不协变

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

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

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