IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> 基于递归解决列表转树形结构问题 -> 正文阅读

[Java知识库]基于递归解决列表转树形结构问题

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


一、列表参数

列表参数需要符合递归所需的关联关系,例如必须父子级关系(子数据的parentId需要为父级的id),未进行关联的数据无法在树形结构中显示。

package com.vshi.util.entity;

import lombok.Data;

/**
 * @author zzz
 * @since 2022-03-04 15:54
 */
@Data
public class TestTree {

    /**
     * 节点ID
     */
    private String id;

    /**
     * 节点名称
     */
    private String name;

    /**
     * 父节点ID
     */
    private String parentId;

    /**
     * 顺序
     */
    private Integer sort;

    /**
     * 备注
     */
    private String remake;

}

二、响应数据适配(通用接口)

1. 接口方法构建

利用重写方法存储数据,通用适配接口

package com.vshi.util.tree.entity;

import java.util.List;

/**
 * @author zzz
 * @since 2022-03-04 15:07
 */
public interface TreeNode {

    /**
     * 节点ID
     *
     * @return String
     */
    String getId();

    /**
     * 节点名称
     *
     * @return String
     */
    String getName();

    /**
     * 顺序
     *
     * @return Integer
     */
    Integer getSort();

    /**
     * 父节点ID
     *
     * @return String
     */
    String getParentId();

    /**
     * 赋值子节点列表
     *
     * @param childNodes children
     */
    void setChildNodes(List<? extends TreeNode> childNodes);

    /**
     * 子节点列表
     *
     * @return List
     */
    List<? extends TreeNode> getChildNodes();
}

2. 创建响应实体类

利用类的继承和接口实现来构建实体类,增加代码的可读性和复用性。
package com.vshi.util.entity;

import java.util.List;

/**
 * @author zzz
 * @since 2022-03-04 16:48
 */
public class TestTreeVo extends TestTree implements TreeNode {

    private List<TestTreeVo> childNodes;

    @Override
    public void setChildNodes(List<? extends TreeNode> childNodes) {
        this.childNodes = (List<TestTreeVo>) childNodes;
    }

    @Override
    public List<? extends TreeNode> getChildNodes() {
        return this.childNodes;
    }
}

三、树形结构构建

package com.vshi.util;

import com.vshi.util.entity.TreeNode;
import org.springframework.beans.BeanUtils;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author zzz
 * @since 2022-03-02 14:55
 */
public class TreeNodeUtil {

    /**
     * 根结点ID
     */
    public static final String ROOT_ID = "0";

    public static <T> List<TreeNode> buildTreeNode(List<? extends TreeNode> list, Class<T> clazz) {
        if (CollectionUtils.isEmpty(list)) {
            return Collections.emptyList();
        }
        List<TreeNode> dtoList = new ArrayList<>();
        // 子类适配
        list.forEach(x -> {
            T entity = BeanUtils.instantiateClass(clazz);
            TreeNode treeDto = (TreeNode) adapt(x, entity);
            dtoList.add(treeDto);
        });
        // 构造树形
        return buildTree(dtoList, clazz);
    }

    private static <T> List<TreeNode> buildTree(List<TreeNode> dtoList, Class<T> clazz) {
        Map<String, List<TreeNode>> map = new HashMap<>(dtoList.size());
        dtoList.forEach(x -> {
            T entity = BeanUtils.instantiateClass(clazz);
            TreeNode nodeVO = (TreeNode) adapt(x, entity);
            BeanUtils.copyProperties(x, nodeVO);
            List<TreeNode> childNodes = map.getOrDefault(x.getParentId(), new ArrayList<>());
            childNodes.add(nodeVO);
            // 按sort排序
            List<TreeNode> collect = childNodes.stream().sorted(Comparator.comparing(TreeNode::getSort)).collect(Collectors.toList());
            map.put(x.getParentId(), collect);
        });
        // 顶层数据
        List<TreeNode> roots = map.get(ROOT_ID);
        // 处理子节点数据
        processNode(roots, map);
        return roots;
    }

    private static void processNode(List<TreeNode> roots, Map<String, List<TreeNode>> map) {
        if (CollectionUtils.isEmpty(roots)) {
            return;
        }
		// 递归+遍历插入每层数据
        roots.forEach(x -> {
            List<TreeNode> child = map.get(x.getId());
            if (!CollectionUtils.isEmpty(child)) {
                processNode(child, map);
                x.setChildNodes(child);
            }
        });
    }

    private static <T> Object adapt(TreeNode x, T entity) {
        BeanUtils.copyProperties(x, entity);
        return entity;
    }
}

三、总结

两个需要注意的地方,一是构建一个通用的处理接口,可以在通用方法中进行数据的转换;二是利用map集合存储同节点下的数据集,最后递归构建Tree数据。

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-03-06 12:48:23  更:2022-03-06 12:52:35 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 12:11:55-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码