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>)不是一个好方法(我猜的)。

如果有任何错误,请指出来。

广告
将在 10 秒后关闭
bannerAds