【问题标题】:Generics: How to populate a map from arrays?泛型:如何从数组中填充地图?
【发布时间】:2022-01-07 18:14:20
【问题描述】:

我尝试编写一个实用方法,无论键和值的数据类型是什么,它都会从键和值数组填充映射。

  public static <K,V> Map<K,V> fillMap(Map<K,V> map, K[] keys, V[] values) {
    int l= keys.length;
    for (int i=0; i<l; i++)
      map.put(keys[i], values[i]);
    return map;
  }

然后我调用了这个方法

    HashMap<Integer, String> map= new HashMap<>();
    Integer[] keys= IntStream.range(0, 12).boxed().toArray(Integer[]::new);
    String[] values= new String[] {"Jan","Feb","Mar","Apr","Mai","Jun",
                   "Jul","Aug","Sep","Okt","Nov","Dez"};
    map= MyUtil.fillMap(map, keys, values);

并收到错误:
不兼容的类型:不存在类型变量 K,V 的实例,因此 Map 符合 HashMap强>
所有用 的变体替换 的尝试extends Object> 等到目前为止都失败了。 如何解决这个问题?

【问题讨论】:

    标签: java generics collections


    【解决方案1】:

    问题

    在呈现的代码中,我们声明:

    HashMap<Integer, String> map = new HashMap<>();
    

    public static <K,V> Map<K,V> fillMap(Map<K,V> map, K[] keys, V[] values)
    

    因此,如果我们调用

    map = MyUtil.fillMap(map, keys, values);
    

    我们尝试将Map&lt;...&gt;(由MyUtil::fillMap 返回)分配给HashMap&lt;...&gt;。这不起作用,因为 Map 不是 HashMap


    可能的解决方案

    我想到了两种方法来解决这个问题:

    1. 要么改变map的类型,
    2. 或将MyUtil::fillMap 的返回类型设为通用。

    1。更改map的类型:

    我们可以将map的类型从HashMap&lt;...&gt;改为Map&lt;...&gt;

    Map<Integer, String> map = new HashMap<>();
    ...
    map = MyUtil.fillMap(map, keys, values);
    

    Ideone demo

    2。将MyUtil::fillMap 的返回类型设为泛型:

    通过添加一个额外的泛型参数,我们可以使返回类型的具体实现也泛型:

    public static void main(String[] args) {
      HashMap<Integer, String> map = new HashMap<>();
      final Integer[] keys = IntStream.range(0, 12).boxed().toArray(Integer[]::new);
      final String[] values = new String[] {"Jan", "Feb", "Mar", "Apr", "Mai", "Jun",
          "Jul", "Aug", "Sep", "Okt", "Nov", "Dez"};
      map = MyUtil.fillMap(map, keys, values);
      System.out.println(map);
    }
    
    public static <K, V, M extends Map<K, V>> M fillMap(M map, K[] keys, V[] values) {
      final int l = keys.length;
      for (int i = 0; i < l; i++) {
        map.put(keys[i], values[i]);
      }
      return map;
    }
    

    Ideone demo


    奖励:返回值的无状态构造

    如果不需要将使用的映射的具体实现传递给方法,我会提出第三个选项,创建映射以在方法内返回:

    public static <K, V> Map<K, V> fillMap(K[] keys, V[] values) {
      return IntStream.range(0, keys.length)
          .boxed()
          .collect(Collectors.toMap(
              index -> keys[index],
              index -> values[index]));
    }
    

    Ideone demo

    【讨论】:

    • 我不知道将泛型类型包含到 extends Map>,所以第二种方法很有帮助!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-11
    • 2015-09-14
    相关资源
    最近更新 更多