Voici quelques variantes de la réponse de Sotirios Delimanolis , qui était plutôt bonne au départ (+1). Considérer ce qui suit:
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))));
}
Quelques points ici. Le premier est l'utilisation de caractères génériques dans les génériques; cela rend la fonction un peu plus flexible. Un caractère générique serait nécessaire si, par exemple, vous vouliez que la carte de sortie ait une clé qui est une superclasse de la clé de la carte d'entrée:
Map<String, String> input = new HashMap<String, String>();
input.put("string1", "42");
input.put("string2", "41");
Map<CharSequence, Integer> output = transform(input, Integer::parseInt);
(Il existe également un exemple pour les valeurs de la carte, mais il est vraiment artificiel, et j'avoue que le caractère générique borné pour Y n'aide que dans les cas limites.)
Un deuxième point est qu'au lieu d'exécuter le flux sur la carte d'entrée entrySet
, je l'ai exécuté sur keySet
. Cela rend le code un peu plus propre, je pense, au prix d'avoir à extraire des valeurs de la carte plutôt que de l'entrée de la carte. Par ailleurs, j'ai d'abord eu key -> key
comme premier argument toMap()
et cela a échoué avec une erreur d'inférence de type pour une raison quelconque. Le changer en (X key) -> key
fonction, comme l'a fait Function.identity()
.
Une autre variante encore est la suivante:
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;
}
Cela utilise à la Map.forEach()
place des flux. C'est encore plus simple, je pense, car cela évite les collecteurs, qui sont un peu maladroits à utiliser avec les cartes. La raison en est que Map.forEach()
donne la clé et la valeur en tant que paramètres séparés, alors que le flux n'a qu'une seule valeur - et vous devez choisir d'utiliser la clé ou l'entrée de carte comme valeur. Du côté négatif, cela n'a pas la richesse et la bonté des autres approches. :-)
e -> e.getKey()
parMap.Entry::getKey
. Mais c'est une question de goût / style de programmation.