【问题标题】:Merge all elements from Map<String, Object> to one Map<String, Object>将 Map<String, Object> 中的所有元素合并到一个 Map<String, Object>
【发布时间】:2022-01-17 16:43:30
【问题描述】:

有一个MapA,它可能包含MapB,而MapB可能包含MapC……,下面是MapA结构,

Map<String, Object> mapA = new HashMap<>();

Map 中的数据会是这样的

[
K1=V1,
K2=V2,
K3=V3,
node1={K11=V11, K12=V12, node11={K111=V111, K112=V112, K113=V113}, K13=V13, K14=V14},
K4=V4
]

现在我希望这些将所有这些键值合并到一个 Map 中,就像

[
K1=V1,
K2=V2,
K3=V3,
K11=V11, 
K12=V12, 
K111=V111, 
K112=V112, 
K113=V113,
K13=V13, 
K14=V14,
K4=V4
]

我写了一个类似下面的函数

    private Map<String, Object> getMap (Map<String, Object> map) {
    Map<String, Object> mmm = new HashMap<>();
    for (Map.Entry<String, Object> entry : map.entrySet()) {
        String key = entry.getKey();
        Object value = entry.getValue();
        if (value instanceof Map) {
            mmm.putAll(getMap((Map<String, Object>) value));
            return mmm;
        }
         mmm.put(key, value);
    }
    return mmm;
}

【问题讨论】:

  • “结果不正确”。究竟是什么方式?
  • 你得到了什么输出?
  • @tgdavies 我得到的结果是缺少一些字段,例如缺少K4,K13,K14也缺少
  • 我已经弄清楚发生了什么。不能在if语句中return mmm,如果返回,会丢失map后面的字段。
  • @GBMan 你为什么放java-stream标签?您需要使用 Stream API 来实现吗?

标签: java java-stream


【解决方案1】:

正确的一个:

    private Map<String, Object> getMap (Map<String, Object> map) {
    Map<String, Object> mmm = new HashMap<>();
    for (Map.Entry<String, Object> entry : map.entrySet()) {
        String key = entry.getKey();
        Object value = entry.getValue();
        if (value instanceof Map) {
            mmm.putAll(getMap((Map<String, Object>) value));
        } else {
            mmm.put(key, value);
        }
    }
    return mmm;
}

【讨论】:

  • 正如目前所写,您的答案尚不清楚。请edit 添加其他详细信息,以帮助其他人了解这如何解决所提出的问题。你可以找到更多关于如何写好答案的信息in the help center
【解决方案2】:

可以使用Stream::flatMap 将输入映射内容展平为一级映射,但是,应递归调用flatten 方法并使用@SuppressWarnings("unchecked") 注释进行标记,以避免出现有关潜在不安全转换的警告:

@SuppressWarnings("unchecked")    
public static Map<String, Object> flatten(Map<String, Object> map) {
    return map.entrySet()
        .stream()
        .flatMap(e -> (e.getValue() instanceof Map) ?
            flatten((Map<String, Object>) e.getValue()).entrySet().stream() :
            Stream.of(e))
        .collect(Collectors.toMap(
            Map.Entry::getKey,
            Map.Entry::getValue
        ));
}

测试:

Map<String, Object> map = Map.of(
    "K1", "V1",
    "K2", "V2",
    "K3", "V3",
    "node1", Map.of(
        "K11", "V11", 
        "K12", "V12", 
        "node11", Map.of(
            "K111", "V111", 
            "K112", "V112", 
            "K113", "V113"
        ), 
        "K13", "V13", 
        "K14", "V14"
    ),
    "K4", "V4"
);
System.out.println(flatten(map));

输出(未排序):

{K111=V111, K112=V112, K1=V1, K2=V2, K3=V3, K4=V4, K11=V11, K113=V113, K13=V13, K12=V12, K14=V14}

如果需要维护插入顺序并且输入映射和嵌套映射提供排序(即是LinkedHashMapTreeMap),则应将LinkedHashMap提供给收集器并由@返回987654330@方法:

@SuppressWarnings("unchecked")    
public static LinkedHashMap<String, Object> flatten(Map<String, Object> map) {
    return map.entrySet()
        .stream()
        .flatMap(e -> (e.getValue() instanceof Map) 
            ? flatten((Map<String, Object>) e.getValue()).entrySet().stream() 
            : Stream.of(e)
        )
        .collect(Collectors.toMap(
            Map.Entry::getKey,
            Map.Entry::getValue,
            (v1, v2) -> v1,
            LinkedHashMap::new
        ));
}

输出(按插入排序):

{K1=V1, K2=V2, K3=V3, K4=V4, K11=V11, K12=V12, K13=V13, K14=V14, K111=V111, K112=V112, K113=V113}

【讨论】:

  • 是的,你所做的都是正确的。
猜你喜欢
  • 2018-09-22
  • 1970-01-01
  • 2020-08-01
  • 1970-01-01
  • 1970-01-01
  • 2013-05-24
  • 2014-01-29
  • 1970-01-01
  • 2021-04-29
相关资源
最近更新 更多