如果Map<String, Person>
人员在其上有String getName()
(等)方法,我怎样才能将Map<String, Person>
变成Map<String, String>
String
Person::getName()
是通过致电Map<String, String> byNameMap = new HashMap<>();
for (Map.Entry<String, Person> person : people.entrySet()) {
byNameMap.put(person.getKey(), person.getValue().getName());
}
?
Pre-Java 8我使用
people.entrySet()
但我想用流和lambdas来做。
我无法看到如何以功能方式执行此操作:Map / HashMap不会实现Stream
。
Set<Entry<String, Person>>
会返回Entry<String, String>
我可以流式传输,但如何将新的{{1}}添加到目标地图?
答案 0 :(得分:26)
使用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 :(得分:19)
一种方法是使用toMap
收集器:
import static java.util.stream.Collectors.toMap;
Map<String, String> byNameMap = people.entrySet().stream()
.collect(toMap(Entry::getKey,
e -> e.getValue().getName()));
答案 2 :(得分:0)
使用一些我在手头的图书馆里找不到的通用代码
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);
如果您需要密钥以及重映射功能中的值,第二个版本可以实现这一点
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());