Aquí hay algunas variaciones en la respuesta de Sotirios Delimanolis , que fue bastante buena para empezar (+1). Considera lo siguiente:
static <X, Y, Z> Map<X, Z> transform(Map<? extends X, ? extends Y> input,
Function<Y, Z> function) {
return input.keySet().stream()
.collect(Collectors.toMap(Function.identity(),
key -> function.apply(input.get(key))));
}
Un par de puntos aquí. Primero está el uso de comodines en los genéricos; Esto hace que la función sea algo más flexible. Sería necesario un comodín si, por ejemplo, desea que el mapa de salida tenga una clave que sea una superclase de la clave del mapa de entrada:
Map<String, String> input = new HashMap<String, String>();
input.put("string1", "42");
input.put("string2", "41");
Map<CharSequence, Integer> output = transform(input, Integer::parseInt);
(También hay un ejemplo para los valores del mapa, pero es realmente artificial, y admito que tener el comodín delimitado para Y solo ayuda en casos extremos).
Un segundo punto es que, en lugar de ejecutar la secuencia sobre el mapa de entrada entrySet
, la ejecuté sobre keySet
. Esto hace que el código sea un poco más limpio, creo, a costa de tener que recuperar valores del mapa en lugar de hacerlo desde la entrada del mapa. Por cierto, inicialmente tuve key -> key
como primer argumento toMap()
y esto falló con un error de inferencia de tipo por alguna razón. Cambiando a (X key) -> key
trabajado, como lo hizo Function.identity()
.
Todavía otra variación es la siguiente:
static <X, Y, Z> Map<X, Z> transform1(Map<? extends X, ? extends Y> input,
Function<Y, Z> function) {
Map<X, Z> result = new HashMap<>();
input.forEach((k, v) -> result.put(k, function.apply(v)));
return result;
}
Esto utiliza en Map.forEach()
lugar de secuencias. Esto es aún más simple, creo, porque prescinde de los coleccionistas, que son algo torpes de usar con los mapas. La razón es que Map.forEach()
proporciona la clave y el valor como parámetros separados, mientras que la secuencia solo tiene un valor, y debe elegir si usar la clave o la entrada del mapa como ese valor. En el lado negativo, esto carece de la bondad rica y fluida de los otros enfoques. :-)
e -> e.getKey()
conMap.Entry::getKey
. Pero eso es una cuestión de gusto / estilo de programación.