Ось декілька варіантів відповіді Сотіріоса Деліманоліса , який почався досить непогано (+1). Розглянемо наступне:
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))));
}
Пару балів тут. По-перше, це використання знакових символів у генериці; це робить функцію дещо гнучкішою. Підстановочний знак буде необхідним, якщо, наприклад, ви хотіли, щоб у вихідній карті був ключ, який є надкласом ключа вхідної карти:
Map<String, String> input = new HashMap<String, String>();
input.put("string1", "42");
input.put("string2", "41");
Map<CharSequence, Integer> output = transform(input, Integer::parseInt);
(Також є приклад для значень карти, але це дійсно надумано, і я визнаю, що обмеження малого підключення для Y допомагає лише у крайніх випадках.)
Другий момент полягає в тому, що замість запуску потоку над вхідною картою entrySet
я провів його над keySet
. Я думаю, що це робить трохи чистішим, я думаю, ціною вибору значень з карти, а не з карти. Між іншим, я спочатку мав key -> key
як перший аргумент, toMap()
і це не вдалося з помилкою виводу типу чомусь. Змінивши його на (X key) -> key
працюючий, як це зробили Function.identity()
.
Ще одна варіація полягає в наступному:
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;
}
Для цього використовується Map.forEach()
замість потоків. Думаю, це ще простіше, тому що він обходиться з колекторами, які є дещо незграбними для використання з картами. Причина полягає в тому, що він Map.forEach()
надає ключ і значення як окремі параметри, тоді як потік має лише одне значення - і ви повинні вибрати, чи використовувати цей ключ або запис карти в якості цього значення. З боку мінусу, цього не вистачає багатої, поточної доброти інших підходів. :-)
e -> e.getKey()
наMap.Entry::getKey
. Але це питання смаку / стилю програмування.