如果需要返回一个树状结构的对象到前端,如何将表里的数据构造成一个树状结构的对象?算法时间复杂度如何?

我们先定义一个名为GoodsCategory的类

字段类型备注
categoryIdInteger分类id
categoryLevelInteger分类级别(一级分类、二级分类、三级分类)
parentIdInteger父分类id
categoryNameString分类名称
categoryRankInteger排序值

按照以往的思路,想要给前端返回一个树状结构,也就是层级目录,只需要多次递归封装就行,简单来说就是:先拿到一级分类的数据(categoryLevel = 1),再获取二级分类的数据(categoryLevel = 2),筛选出二级分类中parentId为一级分类的,封装到对应的一级分类下;同样的,二级分类下也就许多三级分类,这就形成了递归调用,也就是一级分类的for循环下有二级分类的for循环,二级分类的for循环下有三级分类for循环,效率很低

如何改进?用hash表,Java中就是hashMap,由原先的自上而下递归改为自下而上生成,代码如下:

	public List<IndexCategoryVO> getCategoriesForIndexV2() {
		//获取数据库所有分类
        List<GoodsCategory> goodsCategoryList = goodsCategoryService.list();
		//筛选三级分类
        List<GoodsCategory> categoryLevelThreeList = goodsCategoryList.stream().filter(item -> item.getCategoryLevel() == CategoryLevelEnum.LEVEL_THREE.getLevel()).collect(Collectors.toList());
		//筛选二级分类
        List<GoodsCategory> categoryLevelTwoList = goodsCategoryList.stream().filter(item -> item.getCategoryLevel() == CategoryLevelEnum.LEVEL_TWO.getLevel()).collect(Collectors.toList());
		//筛选一级分类
        List<GoodsCategory> categoryLevelOneList = goodsCategoryList.stream().filter(item -> item.getCategoryLevel() == CategoryLevelEnum.LEVEL_ONE.getLevel()).collect(Collectors.toList());

		//生成三级分类map,<父分类id,三级分类>
        Map<Integer, List<ThirdLevelCategoryVO>> categoryLevelThreeMap = new HashMap<>();
        for (GoodsCategory categoryLevelThree:categoryLevelThreeList) {
            List<ThirdLevelCategoryVO> thirdLevelCategoryVOS = categoryLevelThreeMap.get(categoryLevelThree.getParentId());
            if (thirdLevelCategoryVOS == null) {
                thirdLevelCategoryVOS = new ArrayList<>();
            }
            ThirdLevelCategoryVO thirdLevelCategoryVO = new ThirdLevelCategoryVO();
            BeanUtil.copyProperties(categoryLevelThree, thirdLevelCategoryVO);
            thirdLevelCategoryVOS.add(thirdLevelCategoryVO);
            categoryLevelThreeMap.put(categoryLevelThree.getParentId(), thirdLevelCategoryVOS);
        }
		
		//同理生成二级分类map
        Map<Integer, List<SecondLevelCategoryVO>> categoryLevelTwoMap = new HashMap<>();
        for (GoodsCategory categoryLevelTwo:categoryLevelTwoList) {
            List<SecondLevelCategoryVO> secondLevelCategoryVOS = categoryLevelTwoMap.get(categoryLevelTwo.getParentId());
            if (secondLevelCategoryVOS == null) {
                secondLevelCategoryVOS = new ArrayList<>();
            }
            SecondLevelCategoryVO secondLevelCategoryVO = new SecondLevelCategoryVO();
            BeanUtil.copyProperties(categoryLevelTwo, secondLevelCategoryVO);
            secondLevelCategoryVO.setThirdLevelCategoryVOS(categoryLevelThreeMap.get(secondLevelCategoryVO.getCategoryId()));
            secondLevelCategoryVOS.add(secondLevelCategoryVO);
            categoryLevelTwoMap.put(categoryLevelTwo.getParentId(), secondLevelCategoryVOS);
        }
		
		//直接从map里拿二级分类赋给一级分类
        List<IndexCategoryVO> indexCategoryVOList = categoryLevelOneList.stream()
                .map(categoryLevelOne -> {
                    IndexCategoryVO indexCategoryVO = new IndexCategoryVO();
                    BeanUtil.copyProperties(categoryLevelOne, indexCategoryVO);
                    indexCategoryVO.setSecondLevelCategoryVOS(categoryLevelTwoMap.get(indexCategoryVO.getCategoryId()));
                    return indexCategoryVO;
                }).collect(Collectors.toList());

        return indexCategoryVOList;
    }

可以看到,优化后,时间复杂度从O(n3)降到了O(n),经实际项目测试,数据库9条一级分类、28条二级分类、101条三级分类,优化后比优化前效率提升一倍,看来hash表还是挺有用的,减少了递归带来的性能损耗

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值