Oto kilka wariantów odpowiedzi Sotirios Delimanolis , która na początek była całkiem dobra (+1). Rozważ następujące:
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))));
}
Kilka punktów tutaj. Pierwszym z nich jest użycie symboli wieloznacznych w nazwach ogólnych; dzięki temu funkcja jest nieco bardziej elastyczna. Symbol wieloznaczny byłby konieczny, jeśli na przykład chcesz, aby mapa wyjściowa miała klucz, który jest nadklasą klucza mapy wejściowej:
Map<String, String> input = new HashMap<String, String>();
input.put("string1", "42");
input.put("string2", "41");
Map<CharSequence, Integer> output = transform(input, Integer::parseInt);
(Jest też przykład wartości mapy, ale jest ona naprawdę zmyślona i przyznaję, że ograniczenie znaku wieloznacznego dla Y pomaga tylko w skrajnych przypadkach.)
Drugim punktem jest to, że zamiast przepuszczać strumień nad mapą wejściową entrySet
, uruchomiłem go nad keySet
. To sprawia, że kod jest nieco bardziej przejrzysty, kosztem konieczności pobierania wartości z mapy zamiast z wpisu mapy. Nawiasem mówiąc, początkowo miałem key -> key
jako pierwszy argument, toMap()
a to z jakiegoś powodu nie powiodło się z błędem wnioskowania typu. Zmieniłem to na (X key) -> key
działające, tak jak to zrobiłem Function.identity()
.
Jeszcze inna odmiana jest następująca:
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;
}
To używa Map.forEach()
zamiast strumieni. Sądzę, że jest to jeszcze prostsze, ponieważ rezygnuje z kolektorów, których używanie w mapach jest nieco niezdarne. Powodem jest to, że Map.forEach()
podaje klucz i wartość jako osobne parametry, podczas gdy strumień ma tylko jedną wartość - i musisz wybrać, czy użyć klucza, czy wpisu mapy jako tej wartości. Z drugiej strony brakuje w tym bogatej, gwałtownej dobroci innych podejść. :-)
e -> e.getKey()
zMap.Entry::getKey
. Ale to kwestia gustu / stylu programowania.