Hier sind einige Variationen auf Sotirios Delimanolis' answer, das war ziemlich gut mit (+1) zu beginnen. Beachten Sie Folgendes:
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))));
}
Ein paar Punkte hier. Erstens ist die Verwendung von Platzhaltern in den Generika; Dies macht die Funktion etwas flexibler. Ein Platzhalter wäre notwendig, wenn zum Beispiel, können Sie die Ausgabe der Karte wollte einen Schlüssel haben, ist eine übergeordnete Klasse der Eingangskarte Schlüssel:
Map<String, String> input = new HashMap<String, String>();
input.put("string1", "42");
input.put("string2", "41");
Map<CharSequence, Integer> output = transform(input, Integer::parseInt);
(Es ist auch ein Beispiel für die Karte Werte, aber es ist wirklich gekünstelt , und ich gebe zu, dass die begrenzte Wildcard für Y nur in Rand Fällen hilft.)
Ein zweiter Punkt ist, dass statt den Strom über die Eingabe Map entrySet
lief ich es über die keySet
. Das macht den Code ein wenig sauberer, auf Kosten von Werten aus der Map statt aus dem Map-Eintrag. Übrigens hatte ich zunächst key -> key
als erstes Argument zu toMap()
und dies fehlgeschlagen mit einem Typ Inferenz Fehler aus irgendeinem Grund. Ändern Sie es zu (X key) -> key
gearbeitet, wie auch Function.identity()
.
Noch eine andere Variante wie folgt:
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;
}
Dies verwendet Map.forEach()
statt Streams. Das ist noch einfacher, denke ich, weil es auf die Sammler verzichtet, die mit Karten etwas unbeholfen sind. Der Grund dafür ist, dass Map.forEach()
den Schlüssel und den Wert als separate Parameter angibt, während der Stream nur einen Wert hat - und Sie müssen wählen, ob Sie den Schlüssel oder den Map-Eintrag als diesen Wert verwenden möchten. Auf der Minus-Seite mangelt es der reichen, stromreichen Güte der anderen Ansätze. :-)
Sie können ersetzen 'e -> e.getKey()' 'mit Map.Entry :: getKey'. Aber das ist eine Frage des Geschmacks-/Programmierstils. – Holger
Eigentlich ist es eine Frage der Leistung, Ihr Vorschlag ist dem Lambda-Stil etwas überlegen. –