【问题标题】:Flattening a nested Hashmap using Stream使用 Stream 展平嵌套的 Hashmap
【发布时间】:2018-07-10 19:42:57
【问题描述】:

我有一个嵌套的HashMap<String,Object>,我想通过展平哈希图来创建一个HashMap<String,String>。我已经尝试过Recursively Flatten values of nested maps in Java 8 的解决方案。但我无法使用答案中提到的 FlatMap 类。

我也尝试了问题本身的解决方案,但我仍然缺少一些东西。然后我找到了一个类似的用例,并提出了以下解决方案。但似乎我缺少作为 lambda 函数 flatMap 的参数的东西。

public static void main(String[] args) {
  Map<String,Object> stringObjectMap= new HashMap<String,Object>();
  stringObjectMap.put("key1","value1");
  stringObjectMap.put("key2","value2");
  Map<String,Object> innerStringObjectMap = new HashMap<>();
  innerStringObjectMap.put("i1key3","value3");
  innerStringObjectMap.put("i1key4","value4");
  innerStringObjectMap.put("i1key5","value5");
  stringObjectMap.put("map1",innerStringObjectMap);
  Map<String,Object> innerStringObjectMap2 = new HashMap<>();
  innerStringObjectMap.put("i2key6","value6");
  innerStringObjectMap2.put("i2key7","value7");
  innerStringObjectMap.put("i1map2",innerStringObjectMap2);

  Map<String,Object> collect =
        stringObjectMap.entrySet().stream()
                .map(x -> x.getValue())
                .flatMap(x -> x) //I aint sure what should be give here
                .distinct(); //there was a collect as List which i removed.

  //collect.forEach(x -> System.out.println(x));

}

扁平化嵌套地图的更好解决方案是什么?我不仅对值感兴趣,而且对地图中的键感兴趣。这就是为什么我决定将地图展平以获得另一张地图的原因(我不确定这是否可能)

编辑 - 预期输出

key1 - value1
key2-value2
map1 =""  //this is something i will get later for my purpose
i1key3=value3
.
.
i1map2=""
.
.
i2key7=value7

【问题讨论】:

  • 你有一个到 String 和 Map 的映射,这就是为什么你必须声明根级映射是从 String 到 Object 的映射。在入口集中,你只会得到Object,你不知道你是在处理一个字符串还是一个没有类型检查和强制转换的嵌套映射。你应该重新考虑你对这个数据结构的设计。
  • @nickb:因为我对使用流和 Lambda 函数一无所知,所以我所能做的就是调整我在互联网上找到的解决方案。但我会改变数据结构并检查我能做什么。
  • 结果映射中应该包含哪些键?使用嵌套映射,每个值都与两个键相关联,此外,内部映射的键不需要在所有映射中都是唯一的……
  • 我希望值与相应的内部键匹配。我将更新问题以大致了解我所期望的结果。

标签: java dictionary hashmap java-stream flatmap


【解决方案1】:

我使用了https://stackoverflow.com/a/48578105/5243291的函数。但是我以不同的方式使用了该功能。

Map<Object, Object> collect = new HashMap<>();
stringObjectMap.entrySet()
        .stream()
        .flatMap(FlatMap::flatten).forEach(it -> {
          collect.put(it.getKey(), it.getValue());
});

再次发挥作用

public static Stream<Map.Entry<?, ?>> flatten(Map.Entry<?, ?> e) {
if (e.getValue() instanceof Map<?, ?>) {
  return Stream.concat(Stream.of(new AbstractMap.SimpleEntry<>(e.getKey(), "")),
          ((Map<?, ?>) e.getValue()).entrySet().stream().flatMap(FlatMap::flatten));
}

return Stream.of(e);
}

【讨论】:

    【解决方案2】:

    我根据你的需要修改了mentioned answer的类:

    public class FlatMap {
    
      public static Stream<Map.Entry<?, ?>> flatten(Map.Entry<?, ?> e) {
        if (e.getValue() instanceof Map<?, ?>) {
          return Stream.concat(Stream.of(new AbstractMap.SimpleEntry<>(e.getKey(), "")),
                               ((Map<?, ?>) e.getValue()).entrySet().stream().flatMap(FlatMap::flatten));
        }
    
        return Stream.of(e);
      }
    }
    

    用法:

    Map<?, ?> collect = stringObjectMap.entrySet()
                                       .stream()
                                       .flatMap(FlatMap::flatten)
                                       .collect(Collectors.toMap(
                                           Map.Entry::getKey,
                                           Map.Entry::getValue,
                                           (u, v) -> throw new IllegalStateException(String.format("Duplicate key %s", u)),
                                           LinkedHashMap::new));
    

    注意:
    请务必使用提供的collectLinkedHashMap,否则订单将被搞砸。

    【讨论】:

    • 我无法完全那样使用​​它。但我使用了 flatten 功能。 用法 Map&lt;Object, Object&gt; collect = new HashMap&lt;&gt;(); stringObjectMap.entrySet() .stream() .flatMap(FlatMap::flatten).forEach(it -&gt; { collect.put(it.getKey(), it.getValue()); });
    • (u,v) 附近有问题。
    猜你喜欢
    • 2017-08-22
    • 1970-01-01
    • 2016-09-29
    • 2019-02-12
    • 2021-11-28
    • 2017-12-26
    • 2018-10-10
    相关资源
    最近更新 更多