LoginSignup
0
0

More than 1 year has passed since last update.

Javaのジェネリクス(備忘録)

Last updated at Posted at 2019-04-23

Mapの値にListを持つ

要求:
Mapの値がListで,かつこのListで管理するオブジェクトにChild extends Parentという関係がある.そして,各Listのインスタンスが存在し,Listの中のオブジェクトをParentとして処理したい.

問題点

ジェネリクスは共変じゃないので,以下ができない

Map<Key, List<Parent>> map1;
Map<Key, List<Child>> map2;
map1 = map2;  // ここでコンパイルエラー

そこで,ワイルドカードを利用する.しかし,以下もNG

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;

見て分かる通り,ワイルドカードを2回使わないといけなかった.
これを利用してメソッドを定義して実行してみた.

  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<Child>からList<Parent>を値に持つMapを返すメソッド

その1

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;
}

その2

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<T>>となるから.Effective Javaによると,「その1」のようにこのメソッドを実行側でワイルドカードを意識させる(e.g., List<? extends T>)ことは良くないとされるため(多分..)

間違い等あればご指摘下さい.

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0