• java返回前端树形结构数据(2种实现方式)


    0.思想

    首先找到一级目录(类别),然后从一级目录(类别)递归获取所有子目录(类别),并组合成为一个“目录树

    1.普通实现:controller层传的是0层,就是一级目录层,从这里开始往下递归。

    1. /**
    2. * 递归查询得到,分类目录数据;(针对前台的)
    3. * @return
    4. */
    5. @Override
    6. public List listCategoryForCustomer() {
    7. //定义一个List,这个List就用来存在最终的查询结果;即,这个List中的直接元素是:所有的parent_id=0,即type=1的,第1级别的目录;
    8. List categoryVOList = new ArrayList();
    9. //我们额外创建recursivelyFindCategories()方法,去实现递归查询的逻辑;
    10. //我们第一次递归查询时,是先查一级目录;(而一级目录的parentId是0)
    11. //该方法第一个参数是:List categoryVOList:用来存放当前级别对应的,所有的下一级目录数据;
    12. // PS:对于【最终返回给前端的List categoryVOList】来说,其所谓的下一级目录就是:所有的parent_id=0,即type=1的,第1级别的目录;
    13. // PS:对于【所有的parent_id=0,即type=1的,第1级别的目录;】来说,其categoryVOList就是【List childCategory属性】,其是用来存放该级别对应的所有的parent_id=1,即type=2的,第2级别的目录;
    14. // PS:对于【所有的parent_id=1,即type=2的,第2级别的目录;】来说,其categoryVOList就是【List childCategory属性】,其是用来存放该级别对应的所有的parent_id=2,即type=3的,第3级别的目录;
    15. //该方法的第二个参数是:当前级别目录的parent_id,即也就是当前级别的上一级目录的id;
    16. //即,第一个参数是【上一级别的List categoryVOList】;第二参数是【下一级别的parent_id,也就是当前级别的id】;
    17. recursivelyFindCategories(categoryVOList, 0);
    18. return categoryVOList;
    19. }
    20. /**
    21. * 递归查询分类目录数据的,具体逻辑;;;其实就是,递归获取所有目录分类和子目录分类,并组合称为一个“目录树”;
    22. * @param categoryVOList :存放所有下级别分类目录的数据;
    23. * @param parentId :某级分类目录的parentId;
    24. */
    25. private void recursivelyFindCategories(List categoryVOList, Integer parentId) {
    26. //首先,根据parent_id,查询出所有该级别的数据;(比如,第一次我们查询的是parent_id=0,即type=1的,第1级别的目录)
    27. List categoryList = categoryMapper.selectCategoriesByParentId(parentId);
    28. //然后,遍历上面查询的该级别的数据;去尝试查询该级别数据的,下一级别的数据;
    29. if (!CollectionUtils.isEmpty(categoryList)) {
    30. //遍历所有查到的当前级别数据,把其放在对应上级目录的【List categoryVOList】中;
    31. for (int i = 0; i < categoryList.size(); i++) {
    32. //获取到【上面查询的,该级别数据中的,一条数据】,把其存储到上级目录的List childCategory属性中;
    33. //自然,如果该级别是【parent_id=0,即type=1的,第1级别的目录】,就是把其存储在最顶级的、返回给前端的那个List categoryVOS中;
    34. Category category = categoryList.get(i);
    35. CategoryVO categoryVo = new CategoryVO();
    36. BeanUtils.copyProperties(category, categoryVo);
    37. categoryVOList.add(categoryVo);
    38. //然后,这一步是关键:针对【每一个当前级别的,目录数据】去递归调用recursivelyFindCategories()方法;
    39. //自然,第一个参数是【当前级别数据的,List childCategory属性】:这是存放所有下级别目录数据的;
    40. //第二个参数是【当前级别数据的id】:这自然是下级别目录数据的parent_id:
    41. recursivelyFindCategories(categoryVo.getChildCategory(), categoryVo.getId());
    42. }
    43. }
    44. }

    2.stream流实现:

    1. /**
    2. * 利用stream 流实现
    3. *
    4. */
    5. @Override
    6. public List listTree() {
    7. //1.查出所有分类
    8. List categories = categoryMapper.selectList();
    9. //转成VO实体集合类
    10. List categoryVOS = new ArrayList<>();
    11. //ArrayListBeanUtils.copyProperties(categories,categoryVOS);
    12. //注意BeanUtils.copyProperties无法直接复制集合,要循环;也可以单独写一个工具类,
    13. //后续补充转换集合工具类
    14. for (Category category:categories
    15. ) {
    16. CategoryVO categoryVO = new CategoryVO();
    17. BeanUtils.copyProperties(category,categoryVO);
    18. categoryVOS.add(categoryVO);
    19. }
    20. //2.组装成父子的树形结构
    21. //2.1 找到所有的一级分类
    22. List collect = categoryVOS.stream().filter(categoryVO -> {
    23. return categoryVO.getParentId() == 0;//一级分类就是父id=0是吧
    24. }).map(menu -> {
    25. menu.setChildCategory(getChildrens(menu,categoryVOS));
    26. return menu;
    27. }).sorted((menu1,menu2)->{//目录排序
    28. return (menu1.getOrderNum() ==null?0:menu1.getOrderNum() )- (menu2.getOrderNum() == null?0:menu2.getOrderNum());
    29. }).collect(Collectors.toList());
    30. return collect;
    31. }
    32. //递归查找所有菜单的子菜单
    33. //root 当前菜单,categoryList是菜单集合
    34. private List getChildrens(CategoryVO root, List categoryList) {
    35. //找出当前菜单的子菜单
    36. List children = categoryList.stream().filter(categoryVO -> {
    37. //当前菜单root的id等于(是)菜单集合中菜单的父Id,那就意味着当前菜单就是子菜单
    38. //当前菜单root的id,是其他菜单的父id,意味着当前菜单的子菜单找到了呗
    39. return categoryVO.getParentId() == root.getId();
    40. }).map(categoryVO -> {
    41. //找到子菜单
    42. categoryVO.setChildCategory(getChildrens(categoryVO, categoryList));
    43. return categoryVO;
    44. }).sorted((menu1,menu2)->{
    45. //菜单的排序
    46. return (menu1.getOrderNum() ==null?0:menu1.getOrderNum() )- (menu2.getOrderNum() == null?0:menu2.getOrderNum());
    47. }).collect(Collectors.toList());
    48. return children;
    49. }

    3.实体类集合专VO类集合的工具类

    入参为未知类型的实体集合与目标集合的泛型字节码类型(类名.class)

    创建一个新集合用来存储最终结果,泛型为目标类型T

    遍历循环实体集合

    通过Class获取构造器并创建新的实例

    使用BeanUtils.copyProperties,将实体数据拷贝到目标类型

    将拷贝过数据的目标类型添加到集合中

    1. public static List entityListToVOList(List list, Class clazz) {
    2. List result = new ArrayList<>(list.size());
    3. for (Object source : list) {
    4. T target;
    5. try {
    6. target = clazz.getDeclaredConstructor().newInstance();
    7. } catch (Exception e) {
    8. throw new RuntimeException();
    9. }
    10. BeanUtils.copyProperties(source, target);
    11. result.add(target);
    12. }
    13. return result;
    14. }

  • 相关阅读:
    基于物联网的教室人数检测系统-设计说明书
    互联网性能和可用性优化CDN和DNS
    如何通过 Java 合并和取消合并 Excel 单元格
    BUUCTF 隐藏的钥匙 1
    Apollo:前端开发者的全栈探索之旅
    【Java】使用原生Java实现MVC的基本思路(廖雪峰Java学习笔记)
    2023.10.20
    亚马逊云科技基于 Polygon 推出首款 Amazon Managed Blockchain Access,助 Web3 开发人员降低区块链节点运行成本
    无线渗透_COWPATTY破解密码
    Python自然语言处理的力量:NLTK库介绍
  • 原文地址:https://blog.csdn.net/qq_35207086/article/details/133764215