泛型:如何从数组填充地图?
Generics: How to populate a map from arrays?
我尝试编写一个实用程序方法,无论键和值的数据类型是什么,它都会从键和值数组填充映射。
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> 等到目前为止都失败了。
如何解决?
问题
在提供的代码中,我们声明:
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<...>
(由 MyUtil::fillMap
编辑的 return)分配给 HashMap<...>
。这行不通,因为 Map
不是 HashMap
。
可能的解决方案
我想到了两种方法来解决这个问题:
- 要么改变
map
, 的类型
- 或者使
MyUtil::fillMap
的 return 类型通用。
1。更改 map
的类型:
我们可以将 map
的类型从 HashMap<...>
更改为 Map<...>
:
Map<Integer, String> map = new HashMap<>();
...
map = MyUtil.fillMap(map, keys, values);
2。使 MyUtil::fillMap
的 return 类型通用:
通过添加一个额外的泛型参数,我们也可以使 return 类型的具体实现泛化:
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;
}
奖励:return-value
的无状态构造
如果不需要传入用于该方法的映射的具体实现,我会提出第三个选项,即在方法内创建到 return 的映射:
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]));
}
我尝试编写一个实用程序方法,无论键和值的数据类型是什么,它都会从键和值数组填充映射。
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
所有试图用 extends Object> 等到目前为止都失败了。
如何解决?
问题
在提供的代码中,我们声明:
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<...>
(由 MyUtil::fillMap
编辑的 return)分配给 HashMap<...>
。这行不通,因为 Map
不是 HashMap
。
可能的解决方案
我想到了两种方法来解决这个问题:
- 要么改变
map
, 的类型
- 或者使
MyUtil::fillMap
的 return 类型通用。
1。更改 map
的类型:
我们可以将 map
的类型从 HashMap<...>
更改为 Map<...>
:
Map<Integer, String> map = new HashMap<>();
...
map = MyUtil.fillMap(map, keys, values);
2。使 MyUtil::fillMap
的 return 类型通用:
通过添加一个额外的泛型参数,我们也可以使 return 类型的具体实现泛化:
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;
}
奖励:return-value
的无状态构造如果不需要传入用于该方法的映射的具体实现,我会提出第三个选项,即在方法内创建到 return 的映射:
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]));
}