使用流,如何在HashMap中映射值?

时间:2014-04-03 14:03:49

标签: java java-8 java-stream

如果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}}添加到目标地图?

3 个答案:

答案 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());