¿Tienes un Map<String, ? extends Map<String, Integer>> mapOfMaps
.
Map<String, Integer> result = mapOfMaps.get("aaa");
funciona, pero
Map<String, Integer> result = mapOfMaps.getOrDefault("aaa",Collections.emptyMap());
dice
El método getOrDefault(Object, capture#1-of ? extiende Map<String,Integer>) en el tipo Map<String,capture#1-of ? extends Map<String,Integer>> no es aplicable para los argumentos (String, Map<String,Integer>)
Lo mismo va para
Map<String, Integer> result = mapOfMaps.getOrDefault("aaa",Collections.<String,Integer>emptyMap());
o
Map<String, Integer> result = mapOfMaps.getOrDefault("aaa",(Map<String,Integer>)Collections.EMPTY_MAP);
o incluso
Map<String, Integer> result = mapOfMaps.getOrDefault("aaa",new HashMap<String, Integer>());
¿Hay alguna manera de usar getOrDefault de esa manera o tengo que usar la forma torpe?
Map<String, Integer> result = mapOfMaps.get("aaa"); if( result == null ) { result = Collections.emptyMap(); }
Una solución posible, pero aún bastante torpe, es una función de ayuda:
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(); }
y luego llamarlo como
Map<String, Integer> result = getOrEmpty(mapOfMaps,"aaa");
Pero aún preferiría una solución sin tener que definir una función adicional.
Puede usar Collections.unmodifiableMap
para ver su mapa como 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());
Sin embargo, en una sola línea, todavía se ve feo, ya que debe especificar los argumentos de tipo genérico para unmodifiableMap
.
Map<String, Integer> map = Collections.<String, Map<String, Integer>> unmodifiableMap(mapOfMaps).getOrDefault("foo", Collections.emptyMap());
No puede llamar a ningún método que tenga un parámetro de comodín ilimitado o extends
, porque el tipo exacto del comodín no se conoce en tiempo de compilación.
Simplifiquemos esto y veamos Map<String, ? extends Number>
, al que puede asignar cualquiera de
Map<String, ? extends Number> map = new HashMap<String, Integer>(); Map<String, ? extends Number> map = new HashMap<String, Double>();
Sin embargo, al llamar a map.getOrDefault(Object k, V defaultValue)
, no hay forma de determinar el tipo para defaultValue
en tiempo de compilación, ya que el tipo real puede cambiar en tiempo de ejecución, incluso para la misma asignación (aunque no es la misma instancia). ).
// compile-time error, could require a Double or any other Number-type Number i = map.getOrDefault("foo", (Number)Integer.MAX_VALUE);