递归与循环之间的较量,你看好谁

    递归在树结构中经常用到,好处就是代码简洁,不需要写大量的代码,还有就是不怕树的层级加深,拥抱变化。for循环易于理解,但是需要写大量的代码,还有就是对于需求不确定的话,即存在可能未来加深树的层级,就要改动代码了,违背了迪米法则。

   下面的做法也经常遇到,方式1没有在表里加上level等级字段,方式2在表里加上level等级字段,方式3没有在表里加上level等级字段,也发现了一些区别。在数据不是很多情况下,效果略微有点不一样。有些情况下,当然最好的做法是按需加载。

    @GetMapping
    public TagTree list() {
        TagTree root = new TagTree();
        root.setTagId(0L);
        root.setTagName("ceam");

        List<SystemTagDef> list = this.tagDefJpa.findAll();
        long l1 = System.currentTimeMillis();
        buildTree(list);
        long l2 = System.currentTimeMillis();
        System.out.println(">>>>>>>>>>>>>>>>>>>>>>>1="+(l2-l1));

        buildTree2(list);
        long l3 = System.currentTimeMillis();
        System.out.println(">>>>>>>>>>>>>>>>>>>>>>>2="+(l3-l2));

        this.child(root, list);
        long l4 = System.currentTimeMillis();
        System.out.println(">>>>>>>>>>>>>>>>>>>>>>>3="+(l4-l3));
        return root;
    }


    private List<SystemTagDefVO> buildTree(List<SystemTagDef> list) {
        List<SystemTagDefVO> systemTagDefVOList = new ArrayList<>();
        list.forEach(item -> {
            SystemTagDefVO systemTagDefVO = new SystemTagDefVO();
            systemTagDefVO.setTagId(item.getTagId());
            systemTagDefVO.setParentId(item.getParentId());
            systemTagDefVO.setTagName(item.getTagName());
            systemTagDefVOList.add(systemTagDefVO);
        });
        // 取出所有一级的
        List<SystemTagDefVO> collect = systemTagDefVOList.stream()
                .filter(item -> item.getParentId().toString().contains("0"))
                .collect(Collectors.toList());
        systemTagDefVOList.removeAll(collect);
        // 为一级添加二级
        collect.forEach(item -> {
            item.setList(getToo(systemTagDefVOList, item.getTagId().toString()));
            systemTagDefVOList.removeAll(item.getList());
            // 为二级添加三级
            item.getList().forEach(too -> {
                // 移除一级,移除部分二级,最好移除所有二级
                too.setList(getToo(systemTagDefVOList, too.getTagId().toString()));
                // 为三级添加四级
                systemTagDefVOList.removeAll(too.getList());
                too.getList().forEach(three -> {
                    three.setList(getToo(systemTagDefVOList, three.getTagId().toString()));
                    systemTagDefVOList.removeAll(three.getList());
                });
            });
        });
        return collect;
    }

    private List<SystemTagDefVO> buildTree2(List<SystemTagDef> list) {
        List<SystemTagDefVO> systemTagDefVOS = new ArrayList<>();
        list.forEach(item -> {
            SystemTagDefVO systemTagDefVO = new SystemTagDefVO();
            systemTagDefVO.setTagId(item.getTagId());
            systemTagDefVO.setParentId(item.getParentId());
            systemTagDefVO.setTagName(item.getTagName());
            systemTagDefVO.setLevel(item.getLevel());
            systemTagDefVOS.add(systemTagDefVO);
        });

        // 取出所有1级的
        List<SystemTagDefVO> collect = systemTagDefVOS.stream()
                .filter(item -> item.getParentId().toString().contains("0"))
                .collect(Collectors.toList());
        systemTagDefVOS.removeAll(collect);
        // 取出所有2级的
        List<SystemTagDefVO> c2 = systemTagDefVOS.stream()
                .filter(item -> item.getLevel().toString().contains("2"))
                .collect(Collectors.toList());
        systemTagDefVOS.removeAll(c2);
        // 取出所有3级的
        List<SystemTagDefVO> c3 = systemTagDefVOS.stream()
                .filter(item -> item.getLevel().toString().contains("3"))
                .collect(Collectors.toList());
        systemTagDefVOS.removeAll(c3);
        // 取出所有4级的
        List<SystemTagDefVO> c4 = systemTagDefVOS.stream()
                .filter(item -> item.getLevel().toString().contains("4"))
                .collect(Collectors.toList());
        systemTagDefVOS.removeAll(c4);


        //
        collect.forEach(item -> {
            item.setList(getToo(c2, item.getTagId().toString()));
            c2.removeAll(item.getList());

            item.getList().forEach(too -> {

                too.setList(getToo(c3, too.getTagId().toString()));

                c3.removeAll(too.getList());
                too.getList().forEach(three -> {
                    three.setList(getToo(c4, three.getTagId().toString()));
                    c4.removeAll(three.getList());
                });
            });
        });
        return collect;
    }

    private List<SystemTagDefVO> getToo(List<SystemTagDefVO> withOutFirstList, String parentId) {
        List<SystemTagDefVO> collect = withOutFirstList.stream()
                .filter(item -> item.getParentId().toString().contains(parentId))
                .collect(Collectors.toList());
        return collect;
    }

    private void child(TagTree root, List<SystemTagDef> allTags) {
        // 从allTags中取出对应子标签
        List<SystemTagDef> childs = allTags.stream().filter(item ->
                root.getTagId().equals(item.getParentId())).collect(Collectors.toList());
        allTags.removeAll(childs);

        // 注意forEach本身就是有终止条件的,即遍历到最后一个元素
        childs.forEach(item -> {
            TagTree tag = new TagTree();
            tag.setTagId(item.getTagId());
            tag.setTagName(item.getTagName());
            tag.setParentId(item.getParentId());
            // 递归调用
            this.child(tag , allTags);

            root.appendChildren(tag);
        });
    }

表的数据在1000左右

3者的时间如下,都是几毫秒,没有差多少

Hibernate: select systemtagd0_.tag_id as tag_id1_6_, systemtagd0_.crt_time as crt_time2_6_, systemtagd0_.level as level3_6_, systemtagd0_.parent_id as parent_i4_6_, systemtagd0_.tag_desc as tag_desc5_6_, systemtagd0_.tag_name as tag_name6_6_ from tb_tag_def systemtagd0_
>>>>>>>>>>>>>>>>>>>>>>>1=4
>>>>>>>>>>>>>>>>>>>>>>>2=2
>>>>>>>>>>>>>>>>>>>>>>>3=3
Hibernate: select systemtagd0_.tag_id as tag_id1_6_, systemtagd0_.crt_time as crt_time2_6_, systemtagd0_.level as level3_6_, systemtagd0_.parent_id as parent_i4_6_, systemtagd0_.tag_desc as tag_desc5_6_, systemtagd0_.tag_name as tag_name6_6_ from tb_tag_def systemtagd0_
>>>>>>>>>>>>>>>>>>>>>>>1=5
>>>>>>>>>>>>>>>>>>>>>>>2=2
>>>>>>>>>>>>>>>>>>>>>>>3=3
Hibernate: select systemtagd0_.tag_id as tag_id1_6_, systemtagd0_.crt_time as crt_time2_6_, systemtagd0_.level as level3_6_, systemtagd0_.parent_id as parent_i4_6_, systemtagd0_.tag_desc as tag_desc5_6_, systemtagd0_.tag_name as tag_name6_6_ from tb_tag_def systemtagd0_
>>>>>>>>>>>>>>>>>>>>>>>1=5
>>>>>>>>>>>>>>>>>>>>>>>2=2
>>>>>>>>>>>>>>>>>>>>>>>3=5
Hibernate: select systemtagd0_.tag_id as tag_id1_6_, systemtagd0_.crt_time as crt_time2_6_, systemtagd0_.level as level3_6_, systemtagd0_.parent_id as parent_i4_6_, systemtagd0_.tag_desc as tag_desc5_6_, systemtagd0_.tag_name as tag_name6_6_ from tb_tag_def systemtagd0_
>>>>>>>>>>>>>>>>>>>>>>>1=6
>>>>>>>>>>>>>>>>>>>>>>>2=2
>>>>>>>>>>>>>>>>>>>>>>>3=4

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

卡布奇诺-海晨

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值