Java Map.getOrDefault 有界通配符
Java Map.getOrDefault with bounded wildcard
得到一个 Map<String, ? extends Map<String, Integer>> mapOfMaps
变量。
Map<String, Integer> result = mapOfMaps.get("aaa");
有效,但是
Map<String, Integer> result = mapOfMaps.getOrDefault("aaa",Collections.emptyMap());
说
The method getOrDefault(Object, capture#1-of ? extends Map<String,Integer>) in the type Map<String,capture#1-of ? extends Map<String,Integer>> is not applicable for the arguments (String, Map<String,Integer>)
同样适用于
Map<String, Integer> result = mapOfMaps.getOrDefault("aaa",Collections.<String,Integer>emptyMap());
或
Map<String, Integer> result = mapOfMaps.getOrDefault("aaa",(Map<String,Integer>)Collections.EMPTY_MAP);
甚至
Map<String, Integer> result = mapOfMaps.getOrDefault("aaa",new HashMap<String, Integer>());
有没有办法像那样使用 getOrDefault 还是我必须使用笨拙的方法?
Map<String, Integer> result = mapOfMaps.get("aaa");
if( result == null ) {
result = Collections.emptyMap();
}
一个可能但仍然相当笨拙的解决方案是辅助函数:
static <K1, K2, V, M extends Map<K2, V>> Map<K2, V> getOrEmpty(Map<K1, M> mapOfMaps, K1 key) {
Map<K2, V> submap = mapOfMaps.get(key);
return submap != null ? submap : Collections.emptyMap();
}
然后像这样称呼它
Map<String, Integer> result = getOrEmpty(mapOfMaps,"aaa");
但我仍然更喜欢无需定义额外函数的解决方案。
您可以使用 Collections.unmodifiableMap
查看您的地图 Map<String, Map<String, Integer>>
。
Map<String, ? extends Map<String, Integer>> mapOfMaps = new HashMap<>();
Map<String, Map<String, Integer>> view = Collections.unmodifiableMap(mapOfMaps);
Map<String, Integer> map = view.getOrDefault("foo", Collections.emptyMap());
然而,在一行中,它看起来仍然很难看,因为您需要为 unmodifiableMap
.
指定泛型类型参数
Map<String, Integer> map = Collections.<String, Map<String, Integer>>
unmodifiableMap(mapOfMaps).getOrDefault("foo", Collections.emptyMap());
说明
您不能调用任何具有无界或 extends
有界通配符参数的方法,因为通配符的确切类型在编译时未知。
让我们简化一下,看看 Map<String, ? extends Number>
,您可以将其分配给
Map<String, ? extends Number> map = new HashMap<String, Integer>();
Map<String, ? extends Number> map = new HashMap<String, Double>();
然而,当调用 map.getOrDefault(Object k, V defaultValue)
时,无法在编译时确定 defaultValue
的类型,因为实际类型可能会在运行时发生变化,即使对于完全相同的赋值(不是虽然是同一个实例)。
// compile-time error, could require a Double or any other Number-type
Number i = map.getOrDefault("foo", (Number)Integer.MAX_VALUE);
得到一个 Map<String, ? extends Map<String, Integer>> mapOfMaps
变量。
Map<String, Integer> result = mapOfMaps.get("aaa");
有效,但是
Map<String, Integer> result = mapOfMaps.getOrDefault("aaa",Collections.emptyMap());
说
The method getOrDefault(Object, capture#1-of ? extends Map<String,Integer>) in the type Map<String,capture#1-of ? extends Map<String,Integer>> is not applicable for the arguments (String, Map<String,Integer>)
同样适用于
Map<String, Integer> result = mapOfMaps.getOrDefault("aaa",Collections.<String,Integer>emptyMap());
或
Map<String, Integer> result = mapOfMaps.getOrDefault("aaa",(Map<String,Integer>)Collections.EMPTY_MAP);
甚至
Map<String, Integer> result = mapOfMaps.getOrDefault("aaa",new HashMap<String, Integer>());
有没有办法像那样使用 getOrDefault 还是我必须使用笨拙的方法?
Map<String, Integer> result = mapOfMaps.get("aaa");
if( result == null ) {
result = Collections.emptyMap();
}
一个可能但仍然相当笨拙的解决方案是辅助函数:
static <K1, K2, V, M extends Map<K2, V>> Map<K2, V> getOrEmpty(Map<K1, M> mapOfMaps, K1 key) {
Map<K2, V> submap = mapOfMaps.get(key);
return submap != null ? submap : Collections.emptyMap();
}
然后像这样称呼它
Map<String, Integer> result = getOrEmpty(mapOfMaps,"aaa");
但我仍然更喜欢无需定义额外函数的解决方案。
您可以使用 Collections.unmodifiableMap
查看您的地图 Map<String, Map<String, Integer>>
。
Map<String, ? extends Map<String, Integer>> mapOfMaps = new HashMap<>();
Map<String, Map<String, Integer>> view = Collections.unmodifiableMap(mapOfMaps);
Map<String, Integer> map = view.getOrDefault("foo", Collections.emptyMap());
然而,在一行中,它看起来仍然很难看,因为您需要为 unmodifiableMap
.
Map<String, Integer> map = Collections.<String, Map<String, Integer>>
unmodifiableMap(mapOfMaps).getOrDefault("foo", Collections.emptyMap());
说明
您不能调用任何具有无界或 extends
有界通配符参数的方法,因为通配符的确切类型在编译时未知。
让我们简化一下,看看 Map<String, ? extends Number>
,您可以将其分配给
Map<String, ? extends Number> map = new HashMap<String, Integer>();
Map<String, ? extends Number> map = new HashMap<String, Double>();
然而,当调用 map.getOrDefault(Object k, V defaultValue)
时,无法在编译时确定 defaultValue
的类型,因为实际类型可能会在运行时发生变化,即使对于完全相同的赋值(不是虽然是同一个实例)。
// compile-time error, could require a Double or any other Number-type
Number i = map.getOrDefault("foo", (Number)Integer.MAX_VALUE);