【问题标题】:convert from Map<Object,Set<Object>> to Map<String,Set<String>>从 Map<Object,Set<Object>> 转换为 Map<String,Set<String>>
【发布时间】:2018-09-18 11:06:32
【问题描述】:

我有一张地图Map&lt;String, Set&lt;String&gt;&gt;

Map<String, Set<String> result = map.entrySet().parallelStream().collect(
            Collectors.groupingBy(Map.Entry::getValue, Collectors.mapping(Map.Entry::getKey, Collectors.toSet())));

我想将其转换为 Map&lt;String, Set&lt;String&gt;&gt; 。通过对值进行分组并交换键和值的位置。

但是这条线给了我

Type mismatch: cannot convert from Map&lt;Object,Set&lt;Object&gt;&gt; to Map&lt;String,Set&lt;String&gt;&gt;

【问题讨论】:

  • 需要将Object的值解析为String
  • 可能像this ?
  • 您的问题标题与您的问题描述不符。此外,您说您想将映射转换为Map&lt;Set&lt;String&gt;, Set&lt;String&gt;&gt;,但使用完全不同的类型声明result 变量(并且缺少&gt;)。因此,出现编译器错误也就不足为奇了。
  • @Holger 也许Type mismatch: cannot convert from Map&lt;Object,Set&lt;Object&gt;&gt; to Map&lt;String,Set&lt;String&gt;&gt; 是它的症结所在?同意,尽管问题很混乱。
  • @nullpointer 只要 OP 不决定将什么转换为什么,就没有必要考虑编译器错误。有三个完全不同的问题陈述,问题的标题、问题的文本和代码示例。当我更改代码示例以匹配 OP 在文本描述中写的内容时,没有编译器错误。

标签: java java-8 java-stream


【解决方案1】:

您在这里遇到的问题是您正在创建的地图类型是:

Map<Set<String>, Set<String>>

不是Map&lt;String, Set&lt;String&gt;&gt;

因此,您需要先扩展地图的值,例如:

Map<String, Set<String>> collect = map.entrySet()
    .parallelStream()
    // Expand (k, {v1, v2, v3}) to [(v1, k), (v2, k), (v3, k)]
    .flatMap(e -> e.getValue().stream().map(ee -> new SimpleEntry<>(ee, e.getKey())))
    .collect(
        Collectors.groupingBy(
            Map.Entry::getKey,
            Collectors.mapping(Map.Entry::getValue, Collectors.toSet())));

除非您真的需要并行处理,否则我认为使用循环会容易得多:

Map<String, Set<String>> collect = new HashSet<>();
for (Map.Entry<String, Set<String>> entry : map.entrySet()) {
  for (String v : entry.values()) {
      collect.computeIfAbsent(v -> new HashSet<>())
              .add(entry.getKey()));
  }
}

【讨论】:

    【解决方案2】:

    这是一个示例,考虑到您的初始 Map 是 Object to Object。根据需要进行调整。

    Map<Object,Object> map = new HashMap<>();
    Map<String, Set<String>> result = map
                .entrySet()
                .parallelStream()
                .collect(Collectors.groupingBy(entry -> (String) entry.getKey(), 
                         Collectors.mapping(entry -> (String) entry.getKey(), Collectors.toSet())));
    

    您的代码的问题是Map.Entry::getKey 返回一个对象,而不是字符串。

    【讨论】:

    • 我个人更喜欢entry.getKey().toString() 而不是强制转换为字符串,但无论如何都要投赞成票。 :) 当然,我的方法让你可以接受 NullPointerException(因为 Map 的某些实现可以有一个空键,显然你可以有一个空值)。
    • 请注意,您没有做 OP 想要的事情(您根本没有使用地图值)。
    • 嗨@alexrolea,你的回答帮助了我。但就像@AndyTurner 提到的它会生成Map&lt;Set&lt;String&gt;, String&lt;String&gt;&gt;
    【解决方案3】:

    为了避免混淆,我正在回答我的问题。感谢@AndyTurner @alexrolea 指出解决方案。

    Map<Set<String>, Set<String>> result = map.entrySet().parallelStream()
                    .collect(
                    Collectors.groupingBy(entry -> (Set<String>) entry.getValue(), 
                            Collectors.mapping(entry -> entry.getKey(), Collectors.toSet())));
    

    我不得不用 entry -&gt; (Set&lt;String&gt;) entry.getValue() 和另一个替换 Map.Entry::getValue

    这帮助我按值对地图进行分组并将它们用作键。谢谢@nullpointer

    事实上,这也有效。问题是我没有返回正确的数据类型。

    Map<Set<String>, Set<String>> result = map.entrySet().parallelStream()
                    .collect(
                    Collectors.groupingBy(Map.Entry::getValue, 
                            Collectors.mapping(Map.Entry::getKey, Collectors.toSet())));
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-24
      • 2014-01-29
      • 2021-04-26
      • 2015-11-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多