树形结构的一种便捷实现方案
背景
在开发过程中经常需要把平铺的数据结构转为树形的数据结构,例如多级菜单、组织机构等。
实现方案有很多种。
1、可以使用递归查询,但是这样数据一多会导致频繁的多次查询数据库,产生很多额外的IO开销,总体的响应时间会比较慢,一般不会这样做。
2、可以事先查询出来所有的数据,再进行递归的子节点查找,这是一个可行的方案,只需要查询一次数据库,之后的操作利用算法在内存操作,这样响应时间会有一个很大的提升。
3、这里要说的一种方案和第二种类似,只不过采用了google的guava包下的Multimap这种数据结构,利用它可以一个key对应多个值的特性。
方案实现
引入guava包
com.google.guava guava 33.2.0-jre com.alibaba fastjson 1.2.83
树形VO
@Data public class TreeVO { private List children; private int id; private boolean leaf; private String menuName; private int parentId; }
转树示例代码
public static void main(String[] args) { TreeVO v1 = new TreeVO(); v1.setId(10L); v1.setParentId(0L); v1.setMenuName("第一级菜单"); TreeVO v2 = new TreeVO(); v2.setId(11L); v2.setParentId(10L); v2.setMenuName("第二级菜单1"); TreeVO v21 = new TreeVO(); v21.setId(12L); v21.setParentId(10L); v21.setMenuName("第二级菜单2"); TreeVO v3 = new TreeVO(); v3.setId(21L); v3.setParentId(11L); v3.setMenuName("第三级菜单"); Multimap multimap = ArrayListMultimap.create(); multimap.put(v1.getParentId(),v1); multimap.put(v2.getParentId(),v2); multimap.put(v21.getParentId(),v21); multimap.put(v3.getParentId(),v3); Iterator iterator = multimap.values().iterator(); while (iterator.hasNext()) { TreeVOmenuNode = iterator.next(); // 找直接后代 children Collection children = multimap.get(menuNode.getId()); if (children.isEmpty()) { menuNode.setLeaf(true); menuNode.setChildren(null); } else { menuNode.setChildren(children); } } System.out.println(JSON.toJSONString(multimap.get(0L),SerializerFeature.PrettyFormat)); }
这里打印出来的结果是
[
{
"children":[
{
"children":[
{
"id":21,
"leaf":true,
"menuName":"第三级菜单",
"parentId":11
}
],
"id":11,
"leaf":false,
"menuName":"第二级菜单1",
"parentId":10
},
{
"id":12,
"leaf":true,
"menuName":"第二级菜单2",
"parentId":10
}
],
"id":10,
"leaf":false,
"menuName":"第一级菜单",
"parentId":0
}
]