马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
×
Java 中将平铺 List 转换为树形结构
在社交标签、菜单、分类等场景中,数据库通常以平铺的父子关系表存储数据(每条记录带一个 parentId)。前端渲染时往往需要树形结构。本文给出一个基于 Java 的实体定义与“List 转 Tree”实现示例。
一、实体类 SocialTag
标签实体继承基础实体,关键字段包括主键 id、标签名称 tagName、父级 id parentId、标签等级 levelNo、排序号 sortNo、可用状态 enableFlag、删除标识 deleteFlag,并额外维护一个非表字段 childSocialTagList 存放子节点:
- package com.nijia.vip.social.entity;
- import java.util.ArrayList;
- import java.util.List;
- import com.baomidou.mybatisplus.annotation.IdType;
- import com.baomidou.mybatisplus.annotation.TableField;
- import com.baomidou.mybatisplus.annotation.TableId;
- import com.nijia.base.entity.BaseEntity;
- import io.swagger.annotations.ApiModelProperty;
- import lombok.Data;
- /**
- * 社交--个人标签(SocialTag)表实体类
- *
- * @author whp
- * @since 2022-06-23 14:15:53
- */
- @SuppressWarnings("serial")
- @Data
- public class SocialTag extends BaseEntity {
- private static final long serialVersionUID = 1L;
- @TableId(value = "id", type = IdType.ASSIGN_ID)
- @ApiModelProperty("主键")
- private Long id;
- @ApiModelProperty("标签名称")
- private String tagName;
- @ApiModelProperty("父级id")
- private Long parentId;
- @ApiModelProperty("标签等级【1-1级,2-2级】")
- private Integer levelNo;
- @ApiModelProperty("排序号")
- private Integer sortNo;
- @ApiModelProperty("可用状态【1-可用,0-不可用】")
- private Integer enableFlag;
- @ApiModelProperty("删除标识【1-删除,0-正常】")
- private Integer deleteFlag;
- @TableField(exist = false)
- private List<SocialTag> childSocialTagList = new ArrayList<SocialTag>();
- }
复制代码
二、List 转 Tree 的核心算法
思路是先把 List 转成以 id 为键的 Map,再遍历每个节点:若其 parentId 对应的父节点不存在,说明它是顶级节点,加入结果集;否则把它挂到父节点的 childSocialTagList 中。
- private static List<SocialTag> convertListToTree(List<SocialTag> socialTagList) {
- List<SocialTag> resultList = new ArrayList<SocialTag>();
- if (CollectionUtils.isEmpty(socialTagList)) {
- return resultList;
- }
- // List 转为 Map(id -> 节点)
- Map<Long, SocialTag> socialTagMap =
- socialTagList.stream().collect(Collectors.toMap(SocialTag::getId, item -> item));
- for (SocialTag socialTag : socialTagList) {
- SocialTag parentSocialTag = socialTagMap.get(socialTag.getParentId());
- // 该节点为空,说明是顶级节点
- if (parentSocialTag == null) {
- resultList.add(socialTag);
- continue;
- }
- // 把自己加到父节点对象里
- parentSocialTag.getChildSocialTagList().add(socialTag);
- }
- return resultList;
- }
复制代码
三、构造测试数据并验证
通过 initData() 准备两级标签(如 Java/Springboot、DB/Mysql 等),调用转换后打印 JSON:
- public static void main(String[] args) {
- List<SocialTag> resultList = convertListToTree(initData());
- System.out.println(JavaJsonConvert.javaToJson(resultList));
- }
复制代码
其中 initData() 创建若干 SocialTag,设置 id、parentId、levelNo 与创建时间后返回列表。运行后即可得到嵌套了 childSocialTagList 的树形结果。
小结
该实现时间复杂度为 O(n),借助 Map 一次遍历即可完成挂载,比嵌套循环查找父节点更高效,适合标签、菜单等一对多层级数据的后端组装。
qidao123.com企服评测-应用市场 编辑提示
|