如何在Java 8中映射Map中的值?

108

假设我有一个 Map<String, Integer>。有没有一种简单的方法可以从中获取一个 Map<String, String>

所谓简单,我指的不是像这样:

Map<String, String> mapped = new HashMap<>();
for(String key : originalMap.keySet()) {
    mapped.put(key, originalMap.get(key).toString());
}

但是更像一句简短的话:

Map<String, String> mapped = originalMap.mapValues(v -> v.toString());

但是显然没有mapValues方法。


是的,这是一个重复的。抱歉。 - siledh
2个回答

191
您需要流式传递条目并将它们收集到一个新的 Map 中:

您需要流式传递条目并将其收集到新的Map中:

Map<String, String> result = map.entrySet()
    .stream()
    .collect(Collectors.toMap(Entry::getKey, e -> String.valueOf(e.getValue()));

2
我更喜欢这个,而且这甚至只有一行(从技术上讲)。+1 - Rogue
4
请注意,链接的重复答案包括使用Guava的另一种解决方案:Map<String, String> byNameMap = Maps.transformValues(people, Person::getName); "这个方法封装了原始Map,在获取值时进行转换,这意味着只有在实际使用该值时才需要支付转换成本。" - Niccolò

30

最简单的方法是:

Map<String, Integer> map = new HashMap<>();
Map<String, String> mapped = map.entrySet().stream()
        .collect(Collectors.toMap(Map.Entry::getKey, entry -> String.valueOf(entry.getValue())));

你在这里要做的是:

  1. 获得一个 Stream<Map.Entry<String, Integer>>
  2. 将结果收集到最终的映射中:
    1. 将条目映射到它们的键。
    2. 将条目映射到新值,合并 String.valueOf

你不能在一行代码中完成它的原因是,Map 接口没有提供此功能,你能得到的最接近的东西是 map.replaceAll,但该方法要求类型保持不变。


1
这个答案是不正确的,因为它误解了原问题,特别是问题中第一行 Map<String, String> mapped = new HashMap<>(); 的目的。被接受的答案并没有误解问题,并展示了如何在一行内完成此操作。 - Stephen Harrison
1
@StephenHarrison 这是不正确的。我们在概念上有相同的答案。我只是展示 Map<String, Integer> map = new HashMap<>(); 来指示原始映射的来源。 - skiwi
你的代码创建了一个空Map map 和一个在 entrySet 上的 stream(),这个流保证是空的。你的代码会创建两个空的Map Map<String, Integer>Map<String, String>。运行你的代码以找出原因。 - Stephen Harrison
14
我了解这一点。我添加了空地图部分,以表示输出地图的来源。你不能编写一个带有未定义变量的代码示例。 - skiwi
3
@StephenHarrison,我甚至在我的评论中解释了这一点。 - skiwi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接