使用HutoolUtil工具包之树结构工具TreeUtil 快速处理数据树形结构数据,很好很强大!

举报
小米粒-biubiubiu 发表于 2020/12/10 22:25:34 2020/12/10
【摘要】 数据准备 CREATE TABLE `content_file_category` (  `id` bigint(20) NOT NULL AUTO_INCREMENT,  `name` varchar(255) DEFAULT NULL COMMENT '名称',  `parent_id` bigint(20) DEFAULT NULL COMMENT '所属分类',  ...

数据准备


  
  1. CREATE TABLE `content_file_category` (
  2.   `id` bigint(20NOT NULL AUTO_INCREMENT,
  3.   `name` varchar(255DEFAULT NULL COMMENT '名称',
  4.   `parent_id` bigint(20DEFAULT NULL COMMENT '所属分类',
  5.   `order_num` int(11DEFAULT NULL COMMENT '排序序号',
  6.   `level` int(11DEFAULT NULL COMMENT '第几分类,从1开始',
  7.   `gmt_create` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  8.   `gmt_modify` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最近更新时间',
  9.   PRIMARY KEY (`id`),
  10.   KEY `level_idx` (`level`),
  11.   KEY `parent_id_idx` (`parent_id`),
  12.   KEY `name_idx` (`name`)
  13. ENGINE=InnoDB AUTO_INCREMENT=68 DEFAULT CHARSET=utf8 COMMENT='文件分类管理'


 方案一:

一般情况下,我们自己写递归代码的方式

  (1)获取树形结构数据接口


  
  1. /**
  2. * 获取文件分类树形结构
  3. *
  4. * @return
  5. */
  6. @Override
  7. public FileCategoryListResponse queryFileCategoryTree(Integer levelDeep) {
  8. //查询一级分类
  9. List<FileCategoryDO> fileCategoryLevel1 = this.list(new LambdaQueryWrapper<FileCategoryDO>()
  10. .eq(FileCategoryDO::getLevel, FileCategoryLevelEnum.LEVEL_1.getCode())
  11. .orderByAsc(FileCategoryDO::getSort));
  12. //最终响应实体
  13. FileCategoryListResponse response = new FileCategoryListResponse();
  14. List<FileCategoryResponse> fileCategoryResponseList = new ArrayList<FileCategoryResponse>();
  15. if (!CollectionUtils.isEmpty(fileCategoryLevel1)) {
  16. for (FileCategoryDO fileCategoryDO : fileCategoryLevel1) {
  17. FileCategoryResponse fileCategoryResponse = new FileCategoryResponse().setChildren(new ArrayList<>());
  18. BeanUtils.copyProperties(fileCategoryDO, fileCategoryResponse);
  19. //循环遍历一级分类并进行递归操作,组装子分类
  20. getChildrenFileCategory(fileCategoryResponse, levelDeep);
  21. fileCategoryResponseList.add(fileCategoryResponse);
  22. }
  23. }
  24. response.setList(fileCategoryResponseList);
  25. return response;
  26. }
  27. /**
  28. * 递归获取下层级的文件分类
  29. *
  30. * @param fileCategoryResponse
  31. */
  32. private void getChildrenFileCategory(FileCategoryResponse fileCategoryResponse, Integer levelDeep) {
  33. //获取id
  34. if (fileCategoryResponse != null) {
  35. Long id = fileCategoryResponse.getId();
  36. List<FileCategoryDO> list = this.list(new LambdaQueryWrapper<FileCategoryDO>()
  37. .eq(FileCategoryDO::getPid, id).le(FileCategoryDO::getLevel, levelDeep)
  38. .orderByAsc(FileCategoryDO::getSort));
  39. if (!CollectionUtils.isEmpty(list)) {
  40. List<FileCategoryResponse> childrens = list.stream().map(x -> {
  41. FileCategoryResponse dto = new FileCategoryResponse().setChildren(new ArrayList<>());
  42. BeanUtils.copyProperties(x, dto);
  43. return dto;
  44. }).collect(Collectors.toList());
  45. fileCategoryResponse.getChildren().addAll(childrens);
  46. for (FileCategoryResponse categoryResponse : childrens) {
  47. getChildrenFileCategory(categoryResponse, levelDeep);
  48. }
  49. }
  50. }
  51. }

 (2)根据父级id 递归获取子节点id集合


  
  1. /**
  2. * 根据文件分类id获取最下级文件分类id
  3. *
  4. * @param id
  5. * @return
  6. */
  7. @Override
  8. public List<Long> recurQueryCatehoryId(Long id) {
  9. List<FileCategoryResponse> categoryResponses = new CopyOnWriteArrayList<>();
  10. FileCategoryDO fileCategory = this.getById(id);
  11. if (ObjectUtil.isNull(fileCategory)) {
  12. return null;
  13. }
  14. FileCategoryResponse fileCategoryResponse = new FileCategoryResponse().setChildren(new ArrayList<>());
  15. BeanUtils.copyProperties(fileCategory, fileCategoryResponse);
  16. categoryResponses.add(fileCategoryResponse);
  17. //递归获取子节点
  18. getChildrenFileCategory(fileCategoryResponse, FileCategoryLevelEnum.LEVEL_3.getCode());
  19. //将子节点加入到list
  20. categoryResponses = joinChildrenCategoryId(fileCategoryResponse, categoryResponses);
  21. //获取当前文件分类的非1级分类id
  22. List<Long> idList = categoryResponses.stream().filter(x -> x.getLevel() != null && Integer.parseInt(x.getLevel()) > FileCategoryLevelEnum.LEVEL_1.getCode())
  23. .map(FileCategoryResponse::getId).collect(Collectors.toList());
  24. // //根据层级进行分组,key-》层级,value-》每层级的文件分类列表
  25. // Map<String, List<FileCategoryResponse>> collect = categoryResponses.stream().collect(
  26. // Collectors.groupingBy(FileCategoryResponse::getLevel));
  27. // //根据层级key进行倒序,找到key值最大的层级(即最下级分类)
  28. // List<Long> idList = collect.entrySet().stream().sorted((o1, o2) -> o2.getKey().compareTo(o1.getKey())).
  29. // map(x -> x.getValue().stream().map(FileCategoryResponse::getId).collect(Collectors.toList()))
  30. // .findFirst().orElseGet(ArrayList::new);
  31. return idList;
  32. }
  33. private List<FileCategoryResponse> joinChildrenCategoryId(FileCategoryResponse fileCategoryResponse, List<FileCategoryResponse> categoryResponses) {
  34. List<FileCategoryResponse> childrens = fileCategoryResponse.getChildren();
  35. if (!CollectionUtils.isEmpty(childrens)) {
  36. categoryResponses.addAll(childrens);
  37. for (FileCategoryResponse children : childrens) {
  38. joinChildrenCategoryId(children, categoryResponses);
  39. }
  40. }
  41. return categoryResponses;
  42. }

 方案二:

使用 Hutool的 TreeUtil 工具类


  
  1. public static void main(String[] args) {
  2. //模拟的从数据库查询出来的数据
  3. List<FileCategoryDO> fileCategoryDOS = new ArrayList<>();
  4. // 构建node列表
  5. List<TreeNode<String>> nodeList = CollUtil.newArrayList();
  6. List<TreeNode<Long>> collect = fileCategoryDOS.stream().map(fileCategoryDO -> {
  7. Map<String, Object> map = new HashMap<>();
  8. map.put("level", "2");
  9. map.put("gmt_create", LocalDateTime.now());
  10. map.put("gmt_modifier", LocalDateTime.now());
  11. TreeNode<Long> treeNode = new TreeNode<Long>().setId(fileCategoryDO.getId())
  12. .setName(fileCategoryDO.getCategoryName())
  13. .setParentId(Long.parseLong(fileCategoryDO.getPid()))
  14. .setWeight(fileCategoryDO.getSort())
  15. .setExtra(map);
  16. return treeNode;
  17. }).collect(Collectors.toList());
  18. //配置
  19. TreeNodeConfig treeNodeConfig = new TreeNodeConfig();
  20. // 自定义属性名 都要默认值的
  21. treeNodeConfig.setWeightKey("orderNum");
  22. treeNodeConfig.setIdKey("id");
  23. treeNodeConfig.setChildrenKey("childrenNode");
  24. // 最大递归深度
  25. treeNodeConfig.setDeep(3);
  26. //转换器
  27. List<Tree<String>> treeNodes = TreeUtil.build(nodeList, "0", treeNodeConfig,
  28. (treeNode, tree) -> {
  29. tree.setId(treeNode.getId());
  30. tree.setParentId(treeNode.getParentId());
  31. tree.setWeight(treeNode.getWeight());
  32. tree.setName(treeNode.getName());
  33. // 扩展属性 ...
  34. tree.putExtra("level", treeNode.getExtra().getOrDefault("level", 2));
  35. tree.putExtra("gmt_create", treeNode.getExtra().getOrDefault("gmt_create", null));
  36. });
  37. System.out.println(JSON.toJSONString(treeNodes));
  38. }

 

文章来源: blog.csdn.net,作者:血煞风雨城2018,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/qq_31905135/article/details/110952955

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。