Java的泛型(备忘录)
具有List值的Map
要求:
一个要求是,假设Map的值是一个List,并且这个List中的对象满足Child是Parent的关系。还有,每个List实例都存在,并且希望将List中的对象作为Parent进行处理。
请指出问题所在
由于泛型不具备共变性,因此以下操作无法实现。
Map<Key, List<Parent>> map1;
Map<Key, List<Child>> map2;
map1 = map2; // ここでコンパイルエラー
因此,我們可以使用通配符。然而,以下也不可行。
Map<Key, List<? extends Parent>> map1;
Map<Key, List<Child>> map2;
map1 = map2; // ここでコンパイルエラー
这是
List<? extends Parent> list1;
List<Child> list2;
list1 = list2;
我觉得这是奇怪的,尽管它是可行的。然后,下面是正确答案。
Map<Key, ? extends List<? extends Parent>> map1;
Map<Key, List<Child>> map2;
map1 = map2;
就像你所看到的,必须使用两次通配符。
我利用这个来定义并执行了一个方法。
List<Integer> ilist = new ArrayList<Integer>();
ilist.add(1);
ilist.add(2);
ilist.add(3);
Map<String, List<Integer>> imap = new HashMap<String, List<Integer>>();
imap.put("1", ilist);
doit(imap);
public void doit(Map<String, ? extends List<? extends Number>> inmap) {
for (String key : inmap.keySet()) {
System.out.println("key = " + key);
List<? extends Number> list = inmap.get(key);
for (Number n : list) {
System.out.println(n);
}
}
}
额外的:
返回一个具有List作为值的Map的方法,该方法从List中获取该值。
第一个选项
public <V, K extends T, T> Map<V, List<? extends T>> convert(Map<V, List<K>> srcMap) {
Map<V, List<? extends T>> dstMap = new HashMap<V, List<? extends T>>();
for (V key : srcMap.keySet()) {
dstMap.put(key, srcMap.get(key));
}
return dstMap;
}
第二个
public <V, K extends T, T> Map<V, List<T>> toUpper(Map<V, List<K>> srcMap) {
Map<V, List<T>> dstMap = new HashMap<V, List<T>>();
for (V key : srcMap.keySet()) {
List<T> tlist = new ArrayList<T>();
for (K val : srcMap.get(key)) {
tlist.add(val);
}
dstMap.put(key, tlist);
}
return dstMap;
}
可能是因为「2」更好。为什么这么说呢?因为返回类型是Map<V,List>。根据《Effective Java》,让调用方在执行此方法时意识到通配符(例如,List<? extends T>)不是一个好方法(我猜的)。
如果有任何错误,请指出来。