内存递归生成树形结构

时间:2022-02-22 12:43:20

我们常常在数据库中存在这样的数据,就是id,parent_id.但是我们在页面显示的时候通常需要展现树形结构。在我的项目中我看到小伙伴是用递归查找数据库来生成树的,这样就太恐怖了。IO操作很耗费资源的,我们优化项目减少IO操作就是常用的一种手段。

下面直接上代码:

1、Menu模拟树形表

/**
* Created by carl.zhao on 2016/7/6.
*/

@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@EqualsAndHashCode
public class Menu {

/** 菜单ID */
private Long id;
/** 父菜单ID */
private Long parentId;
/** 菜单名称 */
private String menuName;
/** 子菜单集合 */
private List<Menu> childMenus;

public void addChildMenus(Menu menu){
if(null == childMenus){
childMenus = Lists.newArrayList();
childMenus.add(menu);
return;
}
childMenus.add(menu);
}

}

2、MockManager模拟数据查询并生成树形结构

/**
* Created by carl.zhao on 2016/7/6.
*/

public class MockManager {

public static void main(String[] args) {
List<Menu> menus = getMenusInDB();
List<Menu> firstMenus = Lists.newArrayList();
for(Menu menu : menus){
if(null == menu.getParentId()){
firstMenus.add(menu);
}
}
menus.removeAll(firstMenus);
buildMenuTree(firstMenus, menus);
System.out.println(firstMenus);
}

private static List<Menu> getMenusInDB(){
Menu m1 = Menu.builder().id(1L).menuName("一级菜单1").build();
Menu m2 = Menu.builder().id(2L).menuName("一级菜单2").build();
Menu m3 = Menu.builder().id(3L).menuName("一级菜单3").build();
Menu m4 = Menu.builder().id(11L).parentId(1L).menuName("二级菜单11").build();
Menu m5 = Menu.builder().id(12L).parentId(1L).menuName("二级菜单12").build();
Menu m6 = Menu.builder().id(21L).parentId(2L).menuName("二级菜单21").build();
Menu m7 = Menu.builder().id(22L).parentId(2L).menuName("二级菜单22").build();
Menu m8 = Menu.builder().id(31L).parentId(3L).menuName("二级菜单31").build();
Menu m9 = Menu.builder().id(32L).parentId(3L).menuName("二级菜单32").build();
Menu m10 = Menu.builder().id(111L).parentId(11L).menuName("三级菜单111").build();
Menu m11 = Menu.builder().id(112L).parentId(11L).menuName("三级菜单112").build();
List<Menu> menus = Lists.newArrayList(m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11);
return menus;
}

private static void buildMenuTree(List<Menu> firstMenus, List<Menu> menus){
List<Menu> copyMenus = Lists.newCopyOnWriteArrayList(menus);
for(Menu menu : firstMenus){
for(Menu m : copyMenus){
if(m.getParentId().equals(menu.getId())){
menu.addChildMenus(m);
copyMenus.remove(m);
}
}
}
for(Menu menu : firstMenus){
if(CollectionUtils.isNotEmpty(menu.getChildMenus())){
buildMenuTree(menu.getChildMenus(), copyMenus);
}
}
}

}

3、效果图

内存递归生成树形结构