当前位置: 首页 > article >正文

Java将List转换为Tree数据

思路

  1. 我们首先要知道数据中,哪两列能够体现父子级
  2. 我们需要找到最顶层父 id 是什么,因为只有知道最顶层的父 id,我们才能进行递归
  3. 我们要在不改变数据的原有结构下,而转换为 Tree 结构,那么就需要创建新的结构

代码

/**
 * Date: 2023/10/28
 * Author: PuKun
 * Description: 树形数据ID
 */
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface TreeId {}
/**
 * Date: 2023/10/28
 * Author: PuKun
 * Description: 树形数据的父类id
 */
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface TreeParentId {}
/**
 * Date: 2023/10/28
 * Author: PuKun
 * Description: Tree工具类
 */
public class TreeUtils<T> {
    private Class<T> aClass;

    private Field treeIdField;

    private Field treeParentIdField;

    private final String CHILDREN_KEY = "children";

    public TreeUtils(Class<T> aClass) {
        if (aClass == null) {
            throw new RuntimeException("传入的class为NULL");
        }
        this.aClass = aClass;
        init();
    }

    private void init() {
        Field[] fields = this.aClass.getDeclaredFields();
        for (Field f : fields) {
            if (f.isAnnotationPresent(TreeId.class)) {
                this.treeIdField = f;
            } else if (f.isAnnotationPresent(TreeParentId.class)) {
                this.treeParentIdField = f;
            }
            // 这一步也没什么用,我的想法是如果这两列提前找到,那么就提前结束循环
            if (this.treeIdField != null && this.treeParentIdField != null) {
                break;
            }
        }
        if (this.treeIdField == null || this.treeParentIdField == null) {
            throw new RuntimeException("没有找到相应的注解");
        }
        // 避免因字段为private时,无法访问
        this.treeIdField.setAccessible(true);
        this.treeParentIdField.setAccessible(true);
    }

    public List<HashMap<String, Object>> getTreeData(List<T> data) throws IllegalAccessException {
        Object topParentId = getTopParentId(data);
        return buildTreeData(data, topParentId);
    }

    private Object getTopParentId(List<T> data) throws IllegalAccessException {
        // 获取所有parentId的值
        Map<Object, Integer> parentIdMap = new HashMap<>();
        for (T o : data) {
            Object v = this.treeParentIdField.get(o);
            parentIdMap.put(v, 0);
        }

        // 计算每个parentId的数量
        for (T o : data) {
            Object v = this.treeIdField.get(o);
            if (parentIdMap.containsKey(v)) {
                int keyValue = parentIdMap.get(v);
                parentIdMap.put(v, ++keyValue);
            }
        }

        // 当parentId的数量等于0时,说明当前的parentId没有找到对应的treeId,那么就是最顶层的parentId
        Object topParentId = null;
        Set<Map.Entry<Object, Integer>> entries = parentIdMap.entrySet();
        for (Map.Entry<Object, Integer> e : entries) {
            if (e.getValue() == 0) {
                topParentId = e.getKey();
            }
        }

        return topParentId;
    }

    private List<HashMap<String, Object>> buildTreeData(List<T> data, Object parentId) throws IllegalAccessException {
        List<HashMap<String, Object>> list = new ArrayList<>();
        for (T o : data) {
            Object pid = this.treeParentIdField.get(o);
            Object tid = this.treeIdField.get(o);
            if (pid.equals(parentId)) {
                HashMap<String, Object> map = new HashMap<>();
                Field[] fields = this.aClass.getDeclaredFields();
                for (Field f : fields) {
                    f.setAccessible(true);
                    map.put(f.getName(), f.get(o));
                }
                List<HashMap<String, Object>> children = buildTreeData(data, tid);
                if (children.size() > 0) {
                    map.put(CHILDREN_KEY, children);
                }
                list.add(map);
            }
        }
        return list;
    }
}

/**
 * Date: 2023/11/14
 * Author: PuKun
 * Description: 树形工具类测试
 */
class TreeUtilsTest {

    class Dept {
        @TreeId
        private int id;
        private String deptName;
        @TreeParentId
        private int parentId;

        public Dept(int id, String deptName, int parentId) {
            this.id = id;
            this.deptName = deptName;
            this.parentId = parentId;
        }

        public int getId() {
            return id;
        }

        public void setId(int id) {
            this.id = id;
        }

        public String getDeptName() {
            return deptName;
        }

        public void setDeptName(String deptName) {
            this.deptName = deptName;
        }

        public int getParentId() {
            return parentId;
        }

        public void setParentId(int parentId) {
            this.parentId = parentId;
        }
    }

    class Dept2 {
        @TreeId
        private String id;
        private String deptName;
        @TreeParentId
        private String parentId;

        public Dept2(String id, String deptName, String parentId) {
            this.id = id;
            this.deptName = deptName;
            this.parentId = parentId;
        }

        public String getId() {
            return id;
        }

        public void setId(String id) {
            this.id = id;
        }

        public String getDeptName() {
            return deptName;
        }

        public void setDeptName(String deptName) {
            this.deptName = deptName;
        }

        public String getParentId() {
            return parentId;
        }

        public void setParentId(String parentId) {
            this.parentId = parentId;
        }
    }

    @Test
    void getTreeData() {
        // List<Dept> list = new ArrayList<>();
//        list.add(new Dept(1, "闲简居有限公司", 0));
//        list.add(new Dept(2, "开发部", 1));
//        list.add(new Dept(4, "Java组", 2));
//        list.add(new Dept(5, "前端组", 2));
//        list.add(new Dept(3, "测试部", 1));

//        list.add(new Dept(2, "开发部", 1));
//        list.add(new Dept(4, "Java组", 2));
//        list.add(new Dept(5, "前端组", 2));
//        list.add(new Dept(3, "测试部", 1));


//        TreeUtils<Dept> treeUtils = new TreeUtils<>(Dept.class);
//        List<HashMap<String, Object>> mapList = null;
//        try {
//            mapList = treeUtils.getTreeData(list);
//        } catch (IllegalAccessException e) {
//            Assertions.fail(e.getMessage());
//        }

        List<Dept2> list = new ArrayList<>();
        list.add(new Dept2("1", "闲简居有限公司", "0"));
        list.add(new Dept2("2", "开发部", "1"));
        list.add(new Dept2("4", "Java组", "2"));
        list.add(new Dept2("5", "前端组", "2"));
        list.add(new Dept2("3", "测试部", "1"));


        TreeUtils<Dept2> treeUtils = new TreeUtils<>(Dept2.class);
        List<HashMap<String, Object>> mapList = null;
        try {
            mapList = treeUtils.getTreeData(list);
        } catch (IllegalAccessException e) {
            Assertions.fail(e.getMessage());
        }
        Assertions.assertNotEquals(null, mapList);
        System.out.println(mapList);
    }
}


http://www.kler.cn/a/132394.html

相关文章:

  • 《设计模式》创建型模式总结
  • 深入探索Python集合(Set)的高效应用:数据处理、性能优化与实际案例分析
  • //结构体内存对齐
  • ArkTS组件结构和状态管理
  • 【后端】版本控制
  • (33)iptables设置防火墙策略常用命令(docker环境、非docker环境)
  • Java 12 及Tomcat 部署配置
  • docker自启与容器自启
  • SMB信息泄露的利用
  • upload-labs关卡11(双写后缀名绕过)通关思路
  • Web之CSS笔记
  • Java排序算法之希尔排序
  • 【算法】Java 算法设计模式的应用场景
  • Kafka入门教程与详解(一)
  • Git 分支管理
  • JVM判断对象是否存活之引用计数法、可达性分析
  • 最新AI创作系统ChatGPT系统运营源码+支持GPT-4多模态模型
  • 【C++】泛型编程 ⑥ ( 类模板 | 类模板语法 | 代码示例 )
  • PyCharm中常用插件推荐
  • 【Mysql】学习笔记
  • U-boot(二):主Makefile
  • 大型且复杂项目的资源管理怎么做?
  • 模拟实现一个Linux中的简单版shell
  • 6.docker运行mysql容器-理解容器数据卷
  • 邀请报名|11月24日阿里云原生 Serverless 技术实践营 深圳站
  • 概率论和数理统计(四)方差分析与回归分析