Ecco alcune variazioni sulla risposta di Sotirios Delimanolis , che era abbastanza buona per cominciare (+1). Considera quanto segue:
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 paio di punti qui. Il primo è l'uso di caratteri jolly nei generici; questo rende la funzione un po 'più flessibile. Un carattere jolly sarebbe necessario se, ad esempio, si desidera che la mappa di output abbia una chiave che è una superclasse della chiave della mappa di input:
Map<String, String> input = new HashMap<String, String>();
input.put("string1", "42");
input.put("string2", "41");
Map<CharSequence, Integer> output = transform(input, Integer::parseInt);
(C'è anche un esempio per i valori della mappa, ma è davvero inventato, e ammetto che avere il jolly limitato per Y aiuta solo nei casi limite.)
Un secondo punto è che invece di eseguire lo stream sulla mappa di input entrySet
, l'ho eseguito su keySet
. Questo rende il codice un po 'più pulito, credo, a costo di dover recuperare valori dalla mappa anziché dalla voce della mappa. Per inciso, inizialmente ho avuto key -> key
come primo argomento toMap()
e questo non è riuscito con un errore di inferenza del tipo per qualche motivo. Cambiandolo in (X key) -> key
funzionato, come ha fatto Function.identity()
.
Ancora un'altra variazione è la seguente:
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;
}
Questo utilizza Map.forEach()
invece di flussi. Questo è ancora più semplice, penso, perché fa a meno dei collezionisti, che sono un po 'goffi da usare con le mappe. Il motivo è che Map.forEach()
fornisce la chiave e il valore come parametri separati, mentre lo stream ha un solo valore - e devi scegliere se usare la chiave o la voce della mappa come quel valore. Sul lato negativo, questo manca della bontà ricca e fluida degli altri approcci. :-)
e -> e.getKey()
conMap.Entry::getKey
. Ma è una questione di gusti / stile di programmazione.