Java Map 多层嵌套情况下复杂合并

zeo 2021年02月20日 1,270次浏览

背景

有两个Map m1 m2,都是嵌套多层的,希望将m2合并到m1,合并的方式是

  • m1做主表,m1有的key不能丢
  • m2做副表,m2值不是对象类型(Map)时,把值直接覆盖到m1
  • m2做副表,m2值是对象类型(Map)时,需要展开考虑m2的每个key,展开的每个key遵循以上两步更新给m1

例子

m1 = {a=1, b={x={i=1, y=1}, y=y, z=z}}
m2 = {b={x={i=11}}, c=3}
#合并后
m1 = {a=1, b={x={i=11, y=1}, y=y, z=z}, c=3}

上代码

public class mapTest3 {


    public static void main(String[] args) {
        Map<String, Object> m1 = new HashMap<>();
        Map<String, Object> m2 = new HashMap<>();

        Map<String, Object> x1 = new HashMap<>();
        x1.put("i", 1);
        x1.put("y", 1);
        Map<String, Object> o1 = new HashMap<>();
        o1.put("x", x1);
        o1.put("y", "y");
        o1.put("z", "z");


        m1.put("a", 1);
        m1.put("b", o1);

        Map<String, Object> x2 = new HashMap<>();
        x2.put("i", 11);
        Map<String, Object> o2 = new HashMap<>();
        o2.put("x", x2);

        m2.put("b", o2);
        m2.put("c", 3);


        System.out.println(m1);
        System.out.println(m2);

        //m2第一层的key有m1没有,就直接覆盖,不用计算了
        for (Map.Entry<String, Object> node2 : m2.entrySet()) {
            Object x = m1.get(node2.getKey());
            if (x == null) {
                m1.put(node2.getKey(), m2.get(node2.getKey()));
            }
        }

        loopMap(m1, null, m2);

        System.out.println(m1);
    }


    public static void loopMap(Map<String, Object> m1, String p, Map<String, Object> m2) {
        for (Map.Entry<String, Object> node : m1.entrySet()) {

            if (node.getValue().getClass() == HashMap.class) {
                String path;
                if (p == null) {
                    path = node.getKey();
                } else {
                    path = p + "." + node.getKey();
                }
                loopMap((Map<String, Object>) node.getValue(), path, m2);
            } else {
                if (p != null) {
                    String path = p + "." + node.getKey();
                    Object result = getMapByPath(m2, path);
                    if (result != null) {
                        m1.put(node.getKey(), result);
                    }
                }
            }
        }
    }

    public static Object getMapByPath(Map<String, Object> m2, String path) {
        int point = path.indexOf(".");
        if (point == -1) {
            Object r = m2.get(path);
            return r;
        }

        String key = path.substring(0, point);
        String last = path.substring(point + 1, path.length());
        Object result = m2.get(key);
        if (result == null) {
            return null;
        } else {
            try {
                return getMapByPath((Map<String, Object>) result, last);
            } catch (Exception e) {
                return null;
            }
        }
    }


}