我们先定义一个名为GoodsCategory的类
字段 | 类型 | 备注 |
---|---|---|
categoryId | Integer | 分类id |
categoryLevel | Integer | 分类级别(一级分类、二级分类、三级分类) |
parentId | Integer | 父分类id |
categoryName | String | 分类名称 |
categoryRank | Integer | 排序值 |
按照以往的思路,想要给前端返回一个树状结构,也就是层级目录,只需要多次递归封装就行,简单来说就是:先拿到一级分类的数据(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表还是挺有用的,减少了递归带来的性能损耗