java中list转tree的三种方式

350 阅读1分钟

一、使用递归

private List<NextRouteVO> recursionNextRoute(Long parentId, List<NextRouteVO> menuList) {
    List<NextRouteVO> list = new ArrayList<>();
    
    Optional.ofNullable(menuList).ifPresent(menus -> menus.stream()
            .filter(menu -> parentId.equals(menu.getParentId()))
            .forEach(menu -> {
                // 递归获取子节点
                List<NextRouteVO> children = recursionNextRoute(menu.getId(), menuList);
                menu.setChildren(children);
                list.add(menu);
            }));
    return list;
}

二、使用栈(非递归)

private List<NextRouteVO> getNextRouteByDeque(List<NextRouteVO> menuList) {

    // 栈
    Deque<NextRouteVO> deque = new ArrayDeque<>();
    
    // 存储最后的结果
    List<NextRouteVO> result = menuList.stream()
            .filter(nextRouteVO -> SystemConstants.ROOT_MENU_ID.equals(nextRouteVO.getParentId()))
            .collect(Collectors.toList());
    // 根节点入栈
    deque.addAll(result);


    // 遍历栈
    while (!deque.isEmpty()) {
        NextRouteVO routeVO = deque.pop();
        // 遍历集合,获取符合条件的child
        List<NextRouteVO> children = menuList.stream()
                .filter(nextRouteVO -> routeVO.getId().equals(nextRouteVO.getParentId()))
                .collect(Collectors.toList());
        routeVO.setChildren(children);
        if (CollUtil.isNotEmpty(children)) {
            // 子节点入栈
            deque.addAll(children);
        }
    }

    return result;

}

三、使用Map(非递归)

private List<NextRouteVO> getNextRouteByMap(List<NextRouteVO> menuList) {

    // 将集合转为map结构,key为parentId,value为其对应的list集合
    Map<Long, List<NextRouteVO>> menuMap = menuList.stream()
            .collect(Collectors.groupingBy(NextRouteVO::getParentId));
            
    // 遍历集合,设置其子节点
    for (NextRouteVO nextRouteVO : menuList) {
        if (menuMap.containsKey(nextRouteVO.getId())) {
            nextRouteVO.setChildren(menuMap.get(nextRouteVO.getId()));
        } else {
            nextRouteVO.setChildren(new ArrayList<>());
        }
    }
    
    // 返回根节点的集合
    return nextRouteVOList.stream()
            .filter(nextRouteVO -> SystemConstants.ROOT_MENU_ID.equals(nextRouteVO.getParentId()))
            .collect(Collectors.toList());
}