Java list 数据类型组成 tree
项目中企业组织架构类数据通常需要返回给前端树形结构的数据
目前项目中的企业机构层级关系有 sys_tenant_org 表中的 org_num 字段确定。每个企业在创建时都会创建一个同名的根机构,org_num 分配为 00,之后再创建的子机构或部门,org_num 都会是以 00 开头。例:
根机构(00)
- 子机构(0001)
- 子机构(000101)
- 子部门(000102)
- 子部门(00010201)
- 子部门(0002)
- 子部门(000201)
目前设计同一上级下的同级机构/部门最多 99 个(如果是两位十进制数字,最大就是 99,如需扩展,可以选用更高的进制)
通过一个 org_num 字段,可以找到一个机构/部门的上级,算出机构/部门深度。
所以我们现在以 org_num 字段为基础,设计对象使得可以将查询出的平级数据构造成树形数据对象。业务数据可以自己定义对象并继承 OrgNodeDTO.
@Getter @Setter @Accessors(chain = true) public class OrgNodeDTO implements Serializable { private String orgNum; //机构编码 private List<? super OrgNodeDTO> children; //子机构 public OrgNodeDTO(String orgNum) { this.orgNum = orgNum; this.children = new ArrayList<>(); } }
list 转 tree 的 utils
/** * 节点转换为树形结构 * 依据对象中orgNum字段分级 * * @param parent 需要返回的父节点,通常为根节点,也可以是层级中某一层的节点 * @param treeNodes 要转换的子节点,会将属于parent下的子节点组装到parent下 * @return 返回一个包含了下属节点的节点 */ public static <T extends OrgNodeDTO> T findChildren(T parent, List<T> treeNodes) { for (T child : treeNodes) { if (parent.getOrgNum().equals(child.getOrgNum().substring(0, child.getOrgNum().length() - 2))) { if (parent.getChildren() == null) { parent.setChildren(new ArrayList<>()); } parent.getChildren().add(findChildren(child, treeNodes)); } } return parent; }
此处的转换方法用了递归,还有一种双层 for 循环的方法
public static List<TreeNode> toTree01(List<TreeNode> treeNodes) { List<TreeNode> retList = new ArrayList<>(); for (TreeNode parent : treeNodes) { if ("0".equals(parent.getParentId())) { retList.add(parent); } for (TreeNode child : treeNodes) { if (child.getParentId().equals(parent.getId())) { if (parent.getChildren() == null) { parent.setChildren(new ArrayList<>()); } parent.getChildren().add(child); } } } return retList; }
关于两种方法的效率,虽然说递归会在重复调用函数时会增加耗时和对内存的占用,但考虑到这个功能要处理的元素个数通常不会太多,这里做了 10000 个元素做测试;
测试中发现节点数相同时,最终结果的层级对耗时也是有影响的,可以看到,在数据总量不变的前提下,leaf(叶子)越多则最终层级越少,大概在四层或五层时两种方法的执行效率达到最高。而且两种方法跑起来占用的系统内存基本都在 60-80MB 之间波动(这里直接看的系统任务管理器,直接看的当前运行的程序,这里面也包含了构造数据那部分代码占用的内存,实际只处理数据也用不了这么多内存),最终项目中选用了递归的方法;
(ps 本来想做满树来测试,但是满树会因为层级的变化导致元素总数不断增加,这样变量又增多了,所以最终采用了固定元素个数的测试)
测试代码:https://github.com/mnizht/JDKTest/blob/master/src/cn/zhuht/jdk8test/util/List2Tree.java
结果对比:
特别感谢同事 zsp 的技术支持:https://gitee.com/fantasyzsp/AuthorityService.git
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于