PersonにString getName()
(etc)メソッドが含まれる_Map<String, Person>
_が指定されている場合、_Map<String, Person>
_を_Map<String, String>
_に変換するにはどうすればよいですかString
Person::getName()
?
使用するJava 8より前
_Map<String, String> byNameMap = new HashMap<>();
for (Map.Entry<String, Person> person : people.entrySet()) {
byNameMap.put(person.getKey(), person.getValue().getName());
}
_
しかし、私はストリームとラムダを使用してそれをしたいと思います。
これを機能的なスタイルで行う方法がわかりません:Map/HashMapは Stream
を実装していません。
people.entrySet()
は、ストリーミングできる_Set<Entry<String, Person>>
_を返しますが、新しい_Entry<String, String>
_を宛先マップに追加するにはどうすればよいですか?
Java 8を使用すると、次のことができます。
Map<String, String> byNameMap = new HashMap<>();
people.forEach((k, v) -> byNameMap.put(k, v.getName());
Guavaの Maps.transformValues を使用したほうがよいでしょう。これは、元のMap
をラップし、get
を実行するときに変換を実行します。つまり、実際に値を消費したときの変換コスト。
Guavaを使用すると、次のようになります。
Map<String, String> byNameMap = Maps.transformValues(people, Person::getName);
編集:
@Eelcoのコメントに続いて(そして完全を期すため)、マップへの変換は Collectors.toMap を使用して以下のように行うとより効果的です。
Map<String, String> byNameMap = people.entrySet()
.stream()
.collect(Collectors.toMap(Map.Entry::getKey, (entry) -> entry.getValue().getName());
1つの方法は、toMap
コレクターを使用することです。
import static Java.util.stream.Collectors.toMap;
Map<String, String> byNameMap = people.entrySet().stream()
.collect(toMap(Entry::getKey,
e -> e.getValue().getName()));
悲しいことに、手元にあるライブラリーでは見つけられなかった少し一般的なコードを使用する
public static <K, V1, V2> Map<K, V2> remap(Map<K, V1> map,
Function<? super V1, ? extends V2> function) {
return map.entrySet()
.stream() // or parallel
.collect(Collectors.toMap(
Map.Entry::getKey,
e -> function.apply(e.getValue())
));
}
これは本質的にGuavas Maps.transformValues
から他の人が言及するマイナス面を差し引いたものと同じになります。
Map<String, Person> persons = ...;
Map<String, String> byNameMap = remap(persons, Person::getName);
そして、リマッピング関数のキーと値が必要な場合、この2番目のバージョンはそれを可能にします
public static <K, V1, V2> Map<K, V2> remap(Map<K, V1> map,
BiFunction<? super K, ? super V1, ? extends V2> function) {
return map.entrySet()
.stream() // or parallel
.collect(Collectors.toMap(
Map.Entry::getKey,
e -> function.apply(e.getKey(), e.getValue())
));
}
それは例えばのように使用することができます
Map<String, String> byNameMap = remap(persons, (key, val) -> key + ":" + val.getName());