列表转树 ,数据结构处理,list ->tree

上一篇随笔,说了一下列表转树的操作,但是很有局限性,例如,id必须是自增长,必须现有父id才能有子id,这样就会有一些局限性,特别是自增长,因为不能排序,所以就无法处理。

今天又遇到这个列表转树结构处理,起因是因为测试提了一个bug,一个方法2.5s的相应时间,测试人员强烈要求优化,没办法优化吧。

bug提到我这边,我开始接管这一块内容。

先大致测试了分析一下,大概sql执行1.8s左右,列表转树0.5s左右,看到这些,其他的时间耗费就先不用管了,这两块是大头,搞定这两块就准备收工。

1:sql优化,之前写的sql实在是烂,不想多说,优化之后效率提高,至于提高多少,还要精确测试,这个不再讨论了。

2:列表转树:

之前的代码采用多层循环,和树的层级成方次的关系,O^N的时间复杂度。

不能忍,坚决改,必须采用时间换空间的方法。

 代码如下:

    public static List listToTree(List<JSONObject> list ){
        //空间换时间,所需要的空间,为了防止那些没有根节点的错误节点存在,造成map扩容造成的性能损耗,直接左移一位处理,如果可以保证没有错误的节点或不在意这个优化,可以直接使用list.size()
        HashMap<Object, JSONObject> tempMap = new HashMap<>(list.size()<<1);
        //最顶层的根节点
        List rootList = new ArrayList();

        for (JSONObject node: list) {
            //当前节点名称
            Object id = node.get("deptCode");
            //父节点名称
            Object parentid = node.get("parentCode");
            //处理当前节点,可能先处理父节点时,已经把该节点挂载子节点了,如果没有的话就新建一个
            JSONObject packageBody = tempMap.getOrDefault(id,new JSONObject());
            //把之前添加的children信息拿过来,挂载到现在的node下。putIfAbsent
            node.putIfAbsent("children",packageBody.getOrDefault("children",new ArrayList<>()));
            tempMap.put(id,node);
            //处理顶级节点,parentid为null的情况下,为顶级节点
            if(ObjectUtil.isNull(parentid)){
                rootList.add(node);
            }else{
                //把当前节点挂到父节点下
                //获取父节点,父节点不存在就先初始化一个
                JSONObject parent = tempMap.getOrDefault(parentid,new JSONObject());
                //父节点为空情况
                //1 还没处理到:创建一个, 2 没有父节点的子节点,坏的数据,丢进去,最后不会被挂到根节点下
                ArrayList children = (ArrayList)parent.getOrDefault("children",new ArrayList());
                parent.put("children",children);
                //把当前节点挂载到父节点下
                children.add(node);
                //把父节点也挂到map中放到节点下
                tempMap.put(parentid,parent);
            }

        }
        return rootList;
    }

测试代码如下:

public  static void main(String[] args){

        List<JSONObject> treeNodeList = new ArrayList<>();
        JSONObject  treeNode1 = JSON.parseObject("{'deptCode':'1','parentCode':null,'ms':'ces','name':'ss'}");
        JSONObject treeNode2 =JSON.parseObject("{'deptCode':'2','parentCode':null,'ms':'订单','name':'ss'}");
        JSONObject treeNode3 =JSON.parseObject("{'deptCode':'3','parentCode':'1','ms':'预约','name':'ss'}");
        JSONObject  treeNode4 =JSON.parseObject("{'deptCode':'4','parentCode':'2','ms':'捐献','name':'ss'}");
        JSONObject  treeNode5 =JSON.parseObject("{'deptCode':'5','parentCode':'4','ms':'我的订单','name':'ss'}");
        JSONObject treeNode6 =JSON.parseObject("{'deptCode':'6','parentCode':'4','ms':'个人中心','name':'ss'}");
        JSONObject  treeNode7 = JSON.parseObject("{'deptCode':'7','parentCode':'6','ms':'个人中心2','name':'ss'}");
        JSONObject  treeNode8 = JSON.parseObject("{'deptCode':'8','parentCode':'99','ms':'个人中心3','name':'ss'}");

        treeNodeList.add(treeNode1);
        treeNodeList.add(treeNode6);
        treeNodeList.add(treeNode5);
        treeNodeList.add(treeNode3);
        treeNodeList.add(treeNode4);
        treeNodeList.add(treeNode2);
        treeNodeList.add(treeNode7);
        treeNodeList.add(treeNode8);

        System.out.print(MasterTreeUtil.listToTree(treeNodeList));

    }

  

打印的结果格式化之后:

 

截图没截完,就这样吧。

说明:此方法为扩充上次list转树,parentid不能进行排序做的优化方案,一次排序处理即可。

代码中的deptCode,以及parentCode是排序的关键字,每个项目不同,因为这个是我根据自己已经完成的方案改写,所以就直接硬编码使用了。不要在意这些细节~~~

如果感觉那里不明白,可以看上一篇的理论和说明,这里不再多说了。

最后说一下,最后在我本机测试的结果,该方案1400条数据,三层结构,消耗时间是20ms左右,相比之前优化了25倍。(当然,是我自己的代码,不是这个示例,这个示例还没测试效果,但是大概也不差多少)

最后说一下,看代码里面的,循环里面的 new 对象的处理,这个很难看,因为是示例代码我就不做处理了,你们可以优化一下。^.^   我只做列表转树······

 

posted @ 2020-05-28 17:13  anscript  阅读(736)  评论(0)    收藏  举报