Java如何用递归构造一个n层的树

树的封装类:

public class TreeVO {

    private Long id; // id
    private String text; // 名称
    private Boolean checked; // 是否选中
    private String state;  // 展开还是合并状态
    private Long parentId;  // 指向父级id
    private List children;  // 子节点

    // Getter ... 
    // Setter ...
}

有菜单表如下:

public class Menu{
    private Long menuId;
    private String menuName;
    private Long parentId;
    // 省略其他属性和Getter、Setter
}

本例使用JPA做ORM

/**
  * MenuDao接口
  */
@Repository
public interface MenuDao extends JpaRepository<Menu,Long>,JpaSpecificationExecutor<Menu> {

    List<Menu> findByParentId(Long parentId);

}
/**
  * MenuService实现类
  */
@Service
public class MenuServiceImpl implements MenuService(){

    @Autowired
    MenuDao menuDao;

    public List<TreeVO> createMenuTree(){
        // 存放结果的list
        List<TreeVO> result = new ArrayList<TreeVO>();
        // 从数据库中查询出根节点(即parentId为0的记录)
        List<Menu> menuList= menuDao.findByParentId(0);
        // 循环根节点并生成树
        for(Menu menu : menuList){
            // 构造树对象
            TreeVO tree = new TreeVO();
            // 赋值
            tree.setId(menu.getMenuId());
            tree.setText(menu.getMenuName());
            tree.setParentId(menu.getParentId());
            // 调用递归方法查询所有子节点
            tree.setChildren(findChildren(tree));
            // 添加到结果里面
            result.add(tree);
        }
        return result;
    }

    public List<TreeVO> findChildren(TreeVO treeVO){
    // 如果传入的是空直接返回null
        if(treeVo == null)
            return null;
        // 否则根据传入的对象的id属性获取子节点
        List<Menu> menuList = menuDao.findByParentId(treeVO.getId())
        // 存放某一级数所有子节点的list集合
        List<TreeVO> children = new ArrayList<TreeVO>();
        if(menuList.size() > 0){
            // 如果有子节点,则循环遍历构造子节点的TreeVO对象
            TreeVO vo = null;
            for(Menu menu : menuList){
                // 构造一个对象
                vo = new TreeVO();
                // set...
                vo.setState("closed");
                vo.setIsMenu(true);
                vo.setParentId(treeVO.getId());
                vo.setText(m.getMenuName());
                vo.setId(m.getMenuId());
                // 递归调用获取字某一级数的子节点
                vo.setChildren(createMenuTreeNoFunctoin(vo));
                // 将某一级下的某个节点添加到结果集中
                children.add(vo);
            }
            // 返回结果
            return result;
        } else {
            // 如果没有查询出子节点则返回空
            return null;
        }        
    }

}

本例并不够完美,对数据库做了多次查询操作,但是方便理解
改造方法可以一次查询出所有的Menu在方法中逐渐过滤,可以减少数据库的访问

猜你喜欢

转载自blog.csdn.net/csdn_meng/article/details/81630969
今日推荐