Map list深层嵌套访问增强工具,可以像js 对象一样访问

Posted isv1

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Map list深层嵌套访问增强工具,可以像js 对象一样访问相关的知识,希望对你有一定的参考价值。

背景

    当在基于配置时写软件时,在java世界很不方便。 配置内容特别多很复杂, 在js里,直接定义一个普通对象即可。

但是在java世界 ,常见的是xml、properties、 YML这类,他们的读写访问都不便,常常要针对配置文件写Bean类,当在写软件初期,配置格式经常改动,这种方式工作量相当大。这时很羡慕js或python之类的,他们有良好的数据结构解决。java 尽管map与list的深度嵌套 能与js对象 或与json 进行一一映射,理论上也是万能数据结构,但是map与list的嵌套,那类型转换、null处理烦得不要不要的,嵌套一层两层解析还好,当嵌套5层以上,直接晕死。在这种情况,就很希望能有一个工具,能像js一样对对象进行灵活的读写访问。  这是背景

 

开发说明1:

    js 中 :   

var  obj={  
        id:1
        name:"aa",
        items:[{
           sid:1,
           sname:"saa"}
        ]
}

  我们可以这样使用:

        obj.items[0].sid

       为了简化开发难度,所有的数组访问必须有 一个小圆点,即这种形式访问:

      obj.items.[0].sid

 

      如果不考虑那么点性能话,可以在这上面一层直接 用正则改造,把 obj.items[0].sid 改成   obj.items.[0].sid。  当然,你也可以用字符串手工解析的(效率比正则高)。

 

开发说明2:

    注意本文是原创文章,也还没经过实际生产项目验证过,成熟度还有待提高,尽管有较多的测试,但是由于逻辑复杂,没有全覆盖测试,故不要冒然用于生产上。

 

开发说明3

    非线程安全,用在线程环境中时,注意不要对全局状态变量使用,否则哪怕用锁 也不能100%保障性程安全。

 

背景交待完毕,直接上代码:

     Mapt.java

import java.util.*;

import static com.alibaba.druid.sql.ast.SQLPartitionValue.Operator.List;

public class Mapt {
    /*
     * Map与list相互深层嵌套处理工具。在投放与获取数据时非常快捷方便。
     * 获取或投放数据,必须有k。k 是一个字符串,由小数点分隔成多部份,
     * 每部份对应着一个嵌套层。任意部份如果首尾由中括号括着,对应着List,
     * 否则非最底层部份对应着Map.访问形式类似Js中的对象访问,但是也仅类似,
     * 对于数组(即list)的访问,必须有小数点,比如js中aa[0]是可以的,但
     * 这个工具必须是 aa.[0]的形式访问。
     * Mapt.put(map,"aa.[3].x",2);
     * Object obj = Mapt.get(map,"aa.[3].x");
     * 这是obj是2.
     * Object obj1 = Mapt.get(map,"aa.[3]");
     * 这是obj1是个Map,他只有一个元素。key为x,value为2
     * =============================
     * 注意,put时,如果不存在则创建,如果存在则覆盖。父路径与子路径的数据格式不一致,
     * 且最近操作的key又对应的是父路径时,会以当前操作为准,子路径将被删除。
     * 如: put(aa.bb.[0].dd ,34), 当前执行put("aa.bb",55),那么前一个put会被覆盖即被删除
     *
     */

    /**
     * 注意,在并发环境中,只能在配置阶段进行全局设置,在并发工作状态 禁止设置
     */
    private static String separator = ".";

    /**
     * 注意,在并发环境中,只能在配置阶段进行全局设置,在并发工作状态 禁止设置
     */
    private static boolean friendsKeyBL = false;


    public static boolean isExist(Object target, String k){
        return isExist(target,k,separator);
    }
    public static boolean isExist(Object target, String k, String separator){
        if (k == null || target == null) return false;
        if (friendsKeyBL) {
            k = k.replaceAll("(?<=[A-Z|a-z|0-9|]])([)", ".[");
        }
        String[] strs = k.split(separator);
        Object rst = target;
        for (int i = 0; i < strs.length; i++) {
            String nextKey = null;
            if (i < strs.length - 1) {
                nextKey = strs[i + 1];
            }
            rst = doingGet(rst, strs[i]);
            if(rst==null) return false;

        }
        return rst==null?false:true;
    }

    public static boolean isChildType(Object target, String k,Class typeClass) {
        return isChildType(target, k, typeClass,separator);
    }

    public static boolean isChildType(Object target, String k,Class typeClass, String separator) {
        if (k == null || target == null) return false;
        if (friendsKeyBL) {
            k = k.replaceAll("(?<=[A-Z|a-z|0-9|]])([)", ".[");
        }
        String[] strs = k.split(separator);
        Object rst = target;
        for (int i = 0; i < strs.length; i++) {
            String nextKey = null;
            if (i < strs.length - 1) {
                nextKey = strs[i + 1];
            }
            rst = doingGet(rst, strs[i]);
            if (rst==null) return false;
        }

        if (rst==null) return false;

        return typeClass.isAssignableFrom(rst.getClass());
    }

    public static Object get(Object target, String k) {

        return get(target, k, separator);
    }

    public static Object get(Object target, String k, String separator) {
        if (k == null || target == null) return null;
        if (friendsKeyBL) {
            k = k.replaceAll("(?<=[A-Z|a-z|0-9|]])([)", ".[");
        }
        String[] strs = k.split(separator);
        Object rst = target;
        for (int i = 0; i < strs.length; i++) {
            String nextKey = null;
            if (i < strs.length - 1) {
                nextKey = strs[i + 1];
            }
            rst = doingGet(rst, strs[i]);
            if (rst ==null) return null;
        }

        return rst;
    }

    private static Object doingGet(Object target, String key) {
        if (key == null || target == null) return target;
        key = key.trim();
        if (List.class.isAssignableFrom(target.getClass())) {
            key = key.substring(1, key.length() - 1);
            int pos = Integer.parseInt(key);
            List list = (List) target;

            return list.get(pos);
        } else if (Map.class.isAssignableFrom(target.getClass())) {
            if (key.substring(0, 1).equals("[")) return null;
            Map map = (Map) target;

            Object son = map.get(key);
            return son;
        }
        return null;
    }

    public static Object put(Object target, String k, Object v) {
        return put(target, k, v, separator);
    }

    public static Object put(Object target, String k, Object v, String separator) {
        if (k == null) return target;
        if (friendsKeyBL) {
            k = k.replaceAll("(?<=[A-Z|a-z|0-9|]])([)", ".[");
        }
        String[] strs = k.split(separator);
        if (target == null) target = createObj(k);
        Object rst = target;
        for (int i = 0; i < strs.length; i++) {
            String nextKey = null;
            if (i < strs.length - 1) {
                nextKey = strs[i + 1];
            }
            rst = doingPut(rst, strs[i], nextKey, v);
        }


        return target;
    }

    private static Object doingPut(Object target, String key, String nextKey, Object v) {
        if (key == null || target == null) return target;
        key = key.trim();
        nextKey = nextKey == null ? null : nextKey.trim();
        if (target == null) target = createObj(key);
        if (nextKey == null) {
            return setVal(target, key, v);
        } else {
            return getNext(target, key, nextKey);
        }

    }

    private static Object getNext(Object target, String key, String nextKey) {
        if (List.class.isAssignableFrom(target.getClass())) {
            key = key.substring(1, key.length() - 1);
            int pos = Integer.parseInt(key);
            List list = (List) target;
            int count = list.size();
            for (int i = 0; count + i <= pos; i++) {
                list.add(null);
            }
            Object obj = list.get(pos);
            if (obj == null) {
                obj = createObj(nextKey);
                list.set(pos, obj);
            } else if (nextKey != null &&  !isSameType(obj,nextKey)) {
                obj = createObj(nextKey);
                list.set(pos, obj);
            }
            return obj;
        } else if (Map.class.isAssignableFrom(target.getClass())) {
            if (key.substring(0, 1).equals("[")) return null;
            Map map = (Map) target;
            Object son = map.get(key);
            if (son == null) {
                son = createObj(nextKey);
                map.put(key, son);
            } if (nextKey != null &&  !isSameType(son,nextKey)) {
                son = createObj(nextKey);
                map.put(key,son);
            }
            return son;
        }
        return null;
    }

    private static boolean isSameType(Object obj,String key){
        String tmp="o";
        if (List.class.isAssignableFrom(obj.getClass())){
            tmp="l";
        } else if (Map.class.isAssignableFrom(obj.getClass())){
            tmp="m";
        }

        String r="";
        if(key.substring(0,1).equals("[")){
            r="l";
        } else {
            r="m";
        }

        return tmp.equals(r);
    }
    private static Object createObj(String key) {
        if (key != null && key.indexOf("[") == 0) {
            return new ArrayList<>();
        } else if (key != null && key.indexOf("[") != 0) {
            return new LinkedHashMap<>();
        }
        return null;
    }

    private static Object setVal(Object target, String key, Object v) {
        if (target == null || key == null) return null;
        if (List.class.isAssignableFrom(target.getClass())) {
            key = key.substring(1, key.length() - 1);
            int pos = Integer.parseInt(key);
            List list = (List) target;
            int count = list.size();
            for (int i = 0; count + i <= pos; i++) {
                list.add(null);
            }
            list.set(pos, v);
            return target;
        } else if (Map.class.isAssignableFrom(target.getClass())) {
            if (key.substring(0, 1).equals("[")) return null;

            Map map = (Map) target;
            map.put(key, v);
            return target;
        }
        return null;
    }


    public static String getString(Object target, String k) {
        Object obj = get(target, k);
        if (obj == null) return null;
        return obj.toString();
    }

    public static Integer getInteger(Object target, String k) {
        Object obj = get(target, k);
        if (obj == null) return null;
        return (Integer) obj;
    }

    public static Long getLong(Object target, String k) {
        Object obj = get(target, k);
        if (obj == null) return null;
        return (Long) obj;
    }

    public static Boolean getBoolean(Object target, String k) {
        Object obj = get(target, k);
        if (obj == null) return null;
        return (Boolean) obj;
    }

    public static Date getDate(Object target, String k) {
        Object obj = get(target, k);
        if (obj == null) return null;
        return (Date) obj;
    }

    public static Double getDouble(Object target, String k) {
        Object obj = get(target, k);
        if (obj == null) return null;
        return (Double) obj;
    }

    public static Float getFloat(Object target, String k) {
        Object obj = get(target, k);
        if (obj == null) return null;
        return (Float) obj;
    }

    public static <T> Map<String, T> getMap(Object target, String k) {
        Object obj = get(target, k);
        if (obj == null) return null;
        return (Map<String, T>) obj;
    }

    public static <T> List<T> getList(Object target, String k) {
        Object obj = get(target, k);
        if (obj == null) return null;
        return (List<T>) obj;
    }

    public static <T> T getBean(Object target, String k) {
        Object obj = get(target, k);
        if (obj == null) return null;
        return (T) obj;
    }

    public static String getSeparator() {
        return separator;
    }

    public static void setSeparator(String separator) {
        Mapt.separator = separator;
    }

    public static boolean isFriendsKeyBL() {
        return friendsKeyBL;
    }

    public static void setFriendsKeyBL(boolean friendsKeyBL) {
        Mapt.friendsKeyBL = friendsKeyBL;
    }
}

 

 

测试与使用示例:

技术图片
 1 import com.alibaba.fastjson.JSON;
 2 import com.fyh.mybatisplusdemo.JackJsonUtils;
 3 import com.fyh.mybatisplusdemo.entiy.Man;
 4 import com.fyh.mybatisplusdemo.entiy.ManDetail;
 5 import org.junit.Test;
 6 import org.springframework.cglib.beans.BeanMap;
 7 
 8 import java.util.ArrayList;
 9 import java.util.LinkedHashMap;
10 import java.util.List;
11 import java.util.Map;
12 
13 public class MaptTest {
14 //    @Test
15     public void put(){
16 
17         boolean tmpbl;
18         Map<String,Object> map =new LinkedHashMap<>();
19         Mapt.setFriendsKeyBL(true);
20         Mapt.put(map,"aa.[0]",5);
21         Mapt.put(map,"aa.[3].x",2);
22         Mapt.put(map,"aa.[0].cc.xx","aaaaa");
23         tmpbl=Mapt.isExist(map,"aa.[0].cc");
24         tmpbl=Mapt.isChildType(map,"aa",List.class);
25         Mapt.put(map,"aa.[0].cc.yy","bb");
26         Mapt.put(map,"aa.yy","bb");
27         String xx=JSON.toJSONString(map);
28         System.out.println(xx);
29         Object obj = Mapt.get(map,"aa.[3].x");
30         Object obj1 = Mapt.get(map,"aa.[3]");
31         Map<String,Integer> tmp = Mapt.getMap(map,"aa.[3]");
32 
33         List list =new ArrayList<>();
34         Mapt.put(list,"[1].x.[0].yy.[0].[0].dd",5);
35         Object obj2 =Mapt.get(list,"[1].x.[0].yy.[0].[0]");
36 
37         Object obj3 =Mapt.put(null,"aa.[0]",5);
38         Mapt.put(obj3,"bb.[0]",66);
39         Mapt.put(obj3,"aa.[3].x",2);
40         Object tmpObj = Mapt.get(obj3,"aa.[3].x");
41         System.out.println();
42     }
43 
44 //    @Test
45     public void jsonTest(){
46         boolean tmpbl;
47         Map<String,Object> map =new LinkedHashMap<>();
48         Mapt.setFriendsKeyBL(true);
49         Mapt.put(map,"aa.[0]",5);
50         Mapt.put(map,"aa.[3].x",2);
51         Mapt.put(map,"aa.[0].cc.xx","aaaaa");
52         tmpbl=Mapt.isExist(map,"aa.[0].cc");
53         tmpbl=Mapt.isChildType(map,"aa",List.class);
54         Mapt.put(map,"aa.[0].cc.yy","bb");
55         String jsonstr = JackJsonUtils.toJson(map);
56         System.out.println(jsonstr);
57 
58     }
59 
60     @Test
61     public void beanMapTest(){
62         Man man =new Man();
63         man.setId(1L);
64         man.setName("zhang1");
65         man.setType1("student");
66         List<ManDetail> list = new ArrayList<>();
67         man.setItems(list);
68         ManDetail detail=new ManDetail();
69         detail.setId(1L);
70         detail.setpId(1L);
71         detail.setTel("1111");
72 
73         list.add(detail);
74         detail=new ManDetail();
75         detail.setId(2L);
76         detail.setpId(1L);
77         detail.setTel("222");
78         list.add(detail);
79 
80         String str=JackJsonUtils.toJson(man);
81         Map<String,Object> map =JackJsonUtils.fromJson(str,Map.class );
82         String manDetailStr = Mapt.getJsonString(map,"items.[0]");
83         ManDetail manDetail = JackJsonUtils.fromJson(manDetailStr,ManDetail.class);
84 
85         //展示通过js对象转标准JSON字符串,再转成Map实例
86         String str1=JackJsonUtils.getStdJsonStr("{no:1,name:‘张三‘}");
87         Map<String,Object> map1 =JackJsonUtils.fromJson(str1,Map.class );
88 
89         str1=JackJsonUtils.getStdJsonStr("aa.js","man");
90         map1 =JackJsonUtils.fromJson(str1,Map.class );
91 
92         //兼容spring的 BeanMap所得map的读写
93         map =BeanMap.create(man);
94         str1=Mapt.getString(map,"items.[0].man.name");
95 
96         System.out.println(str);
97     }
98 }
View Code

 

测试用到辅助类

技术图片
 1 public class Man implements Serializable {
 2     private Long id;
 3     private String name;
 4     private String type1;
 5 
 6 
 7     @TableField(exist = false)
 8     private String nameDesc;
 9 
10     @TableField(exist = false)
11     private List<ManDetail>  items;
12     //省略 getter and setter
13 }
View Code
技术图片
1 import java.io.Serializable;
2 
3 public class ManDetail  implements Serializable {
4     private Long id;
5     private  Long pId;
6     private String tel;
7      //省略 getter and setter
8 
9 }
View Code

 

 

 

  
         

   

以上是关于Map list深层嵌套访问增强工具,可以像js 对象一样访问的主要内容,如果未能解决你的问题,请参考以下文章

js 对象的深层嵌套函数对对象属性的访问

@Valid如何校验Map中嵌套的List

List嵌套遍历优化

在js中嵌套java代码

javascript 访问深层嵌套的属性

JAVA中List转换String,String转换List,Map转换String,String转换Map之间的转换工具类(调优)