java 处理树形结构 树形转为list list转为树形


实体类结构:

@Data
@NoArgsConstructor
@AllArgsConstructor
class Node {
    // id
    private Integer id;
    // 父id
    private Integer pId;
    // 名称
    private String name;
    // 祖级id列表
    private List<Integer> ancestors;
    // 子节点
    private List<Node> children;

    public Node(int id, int pId, String name) {
        this.id = id;
        this.pId = pId;
        this.name = name;
    }

    @Override
    public String toString() {
        return "Node{" +
                "id=" + id +
                ", pId=" + pId +
                ", name='" + name + '\'' +
                ", ancestors=" + ancestors +
                ", children=" + children +
                '}';
    }
}

🍇树形转为list

	@Test
    public void test01() {
        // 填充数据
        Node level4 = new Node(4, 3, "level4-01");
        Node level3 = new Node(3, 2, "level3-01");
        Node level2 = new Node(2, 1, "level2-01");
        Node level22 = new Node(22, 1, "level2-02");
        Node level1 = new Node(1, 0, "level1-01");
        List<Node> level3children = new ArrayList<>();
        level3children.add(level4);
        level3.setChildren(level3children);
        List<Node> level2children = new ArrayList<>();
        level2children.add(level3);
        level2.setChildren(level2children);
        List<Node> children = new ArrayList<>();
        children.add(level2);
        children.add(level22);
        level1.setChildren(children);
        System.out.println(level1.toString());
        System.out.println("===============before===============");
        // 树形转为list
        List<Node> result = new ArrayList<>();
        this.recursionTreeToList(result, level1, null);
        for (Node node : result) {
            node.setChildren(null);
            System.out.println(node.toString());
        }
        System.out.println("===============after===============");
    }
    /**
    
     * 递归把传过来的tree转为list
     *
     * @param result     结果集
     * @param root       当前对象
     * @param parentNode 没有传Null
     */
    public void recursionTreeToList(List<Node> result, Node root, Node parentNode) {
        // 如果没有pid那么就赋值
       /* if (parentNode != null) {
            root.setPid(parentNode.getEid());
        }*/
        result.add(root);
        if (CollectionUtils.isEmpty(root.getChildren())) {
            return;
        }
        for (Node child : root.getChildren()) {
            this.recursionTreeToList(result, child, root);
        }
    }

结果如下:
在这里插入图片描述

🍇每个节点对祖级列表的编号List赋值

	@Test
    public void test01() {
        // 填充数据
        Node level4 = new Node(4, 3, "level4-01");
        Node level3 = new Node(3, 2, "level3-01");
        Node level2 = new Node(2, 1, "level2-01");
        Node level22 = new Node(22, 1, "level2-02");
        Node level1 = new Node(1, 0, "level1-01");
        List<Node> level3children = new ArrayList<>();
        level3children.add(level4);
        level3.setChildren(level3children);
        List<Node> level2children = new ArrayList<>();
        level2children.add(level3);
        level2.setChildren(level2children);
        List<Node> children = new ArrayList<>();
        children.add(level2);
        children.add(level22);
        level1.setChildren(children);
        System.out.println(level1.toString());
        System.out.println("===============before===============");
        // 树形转为list
        List<Node> result = new ArrayList<>();
        this.recursionTreeToList(result, level1, null);
        for (Node node : result) {
            node.setChildren(null);
            System.out.println(node.toString());
        }
        System.out.println("===============after===============");
        // 处理祖父列表
        this.handleAncestors(result);
        for (Node node : result) {
            System.out.println(node.toString());
        }
        System.out.println("===============handle ancestors after===============");
    }

    /**
     * 递归把传过来的tree转为list
     *
     * @param result     结果集
     * @param root       当前对象
     * @param parentNode 没有传Null
     */
    public void recursionTreeToList(List<Node> result, Node root, Node parentNode) {
        // 如果没有pid那么就赋值
       /* if (parentNode != null) {
            root.setPid(parentNode.getEid());
        }*/
        result.add(root);
        if (CollectionUtils.isEmpty(root.getChildren())) {
            return;
        }
        for (Node child : root.getChildren()) {
            this.recursionTreeToList(result, child, root);
        }
    }


    List<Integer> ancestors = new ArrayList<>();

    /**
     * 给list赋值祖父节点
     * @param list
     */
    public void handleAncestors(List<Node> list) {
        for (Node node : list) {
            ancestors = new ArrayList<>();
            List<Integer> ancestorsList = this.recursionAncestors(list, node);
            ancestorsList.add(node.getId());
            node.setAncestors(ancestorsList);
        }
    }

    /**
     * 根据当前节点查询他的祖父列表
     * @param list 数据List
     * @param n 当前节点
     * @return 所有父节点
     */
    public List<Integer> recursionAncestors(List<Node> list, Node n) {
        if (n.getId() == null) {
            return ancestors;
        }
        for (Node node : list) {
            if (n.getPId() == node.getId()) {
                this.recursionAncestors(list, node);
                ancestors.add(node.getId());
            }
        }
        return ancestors;
    }

结果如下:
在这里插入图片描述

🍇list转为树形

方式1

 	@Test
    public void test01() {
        // 填充数据
        Node level4 = new Node(4, 3, "level4-01");
        Node level3 = new Node(3, 2, "level3-01");
        Node level2 = new Node(2, 1, "level2-01");
        Node level22 = new Node(22, 1, "level2-02");
        Node level1 = new Node(1, 0, "level1-01");
        List<Node> level3children = new ArrayList<>();
        level3children.add(level4);
        level3.setChildren(level3children);
        List<Node> level2children = new ArrayList<>();
        level2children.add(level3);
        level2.setChildren(level2children);
        List<Node> children = new ArrayList<>();
        children.add(level2);
        children.add(level22);
        level1.setChildren(children);
        System.out.println(level1.toString());
        System.out.println("=============== before Tree To List ===============");
        List<Node> result = new ArrayList<>();
        // 树形转为list
        this.recursionTreeToList(result, level1, null);
        for (Node node : result) {
            node.setChildren(null);
            System.out.println(node.toString());
        }
        System.out.println("=============== after Tree To List ===============");
        // 处理祖父列表
        this.handleAncestors(result);
        for (Node node : result) {
            System.out.println(node.toString());
        }
        System.out.println("===============handle ancestors after===============");
        List<Node> nodes = this.recursionListToTree(result, 0);
        for (Node node : nodes) {
            System.out.println(node.toString());
        }
        System.out.println("=============== after List To Tree ===============");
    }

    /**
     * 递归把传过来的tree转为list
     *
     * @param result     结果集
     * @param root       当前对象
     * @param parentNode 没有传Null
     */
    public void recursionTreeToList(List<Node> result, Node root, Node parentNode) {
        // 如果没有pid那么就赋值
       /* if (parentNode != null) {
            root.setPid(parentNode.getEid());
        }*/
        result.add(root);
        if (CollectionUtils.isEmpty(root.getChildren())) {
            return;
        }
        for (Node child : root.getChildren()) {
            this.recursionTreeToList(result, child, root);
        }
    }

    /**
     * 递归方法把传过来的list转为tree
     *
     * @param tree     父节点对象
     * @param treeList 所有的List
     * @return
     */
    public List<Node> recursionListToTree(List<Node> list, int pId) {
        List<Node> nodes = new ArrayList<>();
        for (Node node : list) {
            // 找出父节点
            if (pId == node.getPId()) {
                // 调用递归方法填充子节点列表
                nodes.add(this.findChildren(node, list));
            }
        }
        return nodes;
    }

    /**
     * 递归方法
     *
     * @param tree     父节点对象
     * @param treeList 所有的List
     * @return
     */
    public Node findChildren(Node tree, List<Node> treeList) {
        for (Node node : treeList) {
            if (tree.getId().equals(node.getPId())) {
                if (CollectionUtils.isEmpty(tree.getChildren())) {
                    tree.setChildren(new ArrayList<>());
                }
                // 递归 调用自身
                tree.getChildren().add(this.findChildren(node, treeList));
            }
        }
        return tree;
    }

    List<Integer> ancestors = new ArrayList<>();

    /**
     * 给list赋值祖父节点
     *
     * @param list
     */
    public void handleAncestors(List<Node> list) {
        for (Node node : list) {
            ancestors = new ArrayList<>();
            List<Integer> ancestorsList = this.recursionAncestors(list, node);
            ancestorsList.add(node.getId());
            node.setAncestors(ancestorsList);
        }
    }

    /**
     * 根据当前节点查询他的祖父列表
     *
     * @param list 数据List
     * @param n    当前节点
     * @return 所有父节点
     */
    public List<Integer> recursionAncestors(List<Node> list, Node n) {
        if (n.getId() == null) {
            return ancestors;
        }
        for (Node node : list) {
            if (n.getPId() == node.getId()) {
                this.recursionAncestors(list, node);
                ancestors.add(node.getId());
            }
        }
        return ancestors;
    }

结果如图:
在这里插入图片描述

方式2(使用stream,如果id是唯一的话,比递归效率快)

    /**
     * stream把传过来的list转为tree
     * 
     * @param tree     父节点对象
     * @param treeList 所有的List
     * @return
     */
    public List<Node> handleListToTree(List<Node> list, int pId) {
         List<Node> nodes = new ArrayList<>();
		 Map<String, List<Node>> nodeMap = list.stream().collect(Collectors.groupingBy(Node::getPId));
		 list.forEach(n -> { n.setChildren(nodeMap.get(n.getPId())); });
		 nodes = list.stream().filter(n -> n.getPId().equals(pId)).collect(Collectors.toList());
		 return nodes;
    }

方式3(使用插件)

1.导入jar包

<dependencies>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>RELEASE</version>
            <scope>test</scope>
        </dependency>
        <!-- https://mvnrepository.com/artifact/junit/junit -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
            <scope>test</scope>
        </dependency>
<!--   -->
        <!-- liu https://mvnrepository.com/artifact/com.google.guava/guava -->
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>29.0-jre</version>
        </dependency>
    </dependencies>

2.编写代码

import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap;
import lombok.*;
import org.junit.Test;

import java.util.*;

/**
 * @author: doris
 * @date: 2023/7/6 13:27
 */
public class TestTree {

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    class Node {
        // id
        private String id;
        // 父id
        private String pId;
        // 名称
        private String name;
        // 祖级id列表 ,
        private String ancestors;
        // 子节点
        private List<Node> children;
    }

    @Test
    public void test01() {
        List<Node> list = new ArrayList<>();
        list.add(new Node("0", "999999", "level", "999999", null));
        list.add(new Node("1", "0", "level1", "999999,0", null));
        list.add(new Node("2", "1", "level2", "999999,0,1", null));
        list.add(new Node("3", "2", "level3", "999999,0,1,2", null));
        System.out.println("======================start======================");
        Multimap<String, Node> myMultimap = ArrayListMultimap.create();
        for (Node node : list) {
            System.out.println(node);
            myMultimap.put(node.getPId(), node);
        }
        Node build = list.get(0);
        Node tree = createTree(build, myMultimap);
        System.out.println(tree);

    }

    /**
     * 创建树形数据
     * @param build 顶点
     * @param myMultimap 树
     * @return
     */
    public Node createTree(Node build, Multimap<String, Node> myMultimap) {
        if (myMultimap.get(build.getId()) != null) {
            List<Node> list = (List<Node>) myMultimap.get(build.getId());
            recursionData(list, myMultimap);
            build.setChildren(list);
        }
        return build;
    }

    public void recursionData(Collection<Node> list, Multimap<String, Node> myMultimap) {
        for (Node node : list) {
            if (myMultimap.get(node.getId()) != null) {
                List<Node> t = (List<Node>) myMultimap.get(node.getId());
                recursionData(t, myMultimap);
                node.setChildren(t);
            }
        }
    }
}

3.结果:
开始数据转换完树形结构

从数据查询树

1.添加数据的时候加入祖父列表字段,方便匹配(推荐)

select * from tb1 where FIND_IN_SET('id',祖父列表字段) > 0

2.Mysql进行树形查询

SELECT DISTINCT tb1.id,  pid 
FROM tb1, ( SELECT @pid := 'id' ) pd 
WHERE
	FIND_IN_SET( pid, @pid ) > 0 
	AND @pid := concat( @pid, ',', id ) 
UNION SELECT id, pid  FROM tb1  WHERE id = 'id ';
  • 4
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
你可以使用递归的方式来将树形结构转为list。具体来说,你可以先将根节点加入list中,然后递归处理每个子节点,并将它们加入list中。实现代码如下: ```java public List<TreeNode> flatten(TreeNode root) { List<TreeNode> result = new ArrayList<>(); flattenHelper(root, result); return result; } private void flattenHelper(TreeNode node, List<TreeNode> result) { result.add(node); for (TreeNode child : node.getChildren()) { flattenHelper(child, result); } } ``` 这里假设树节点的定义如下: ```java public class TreeNode { private int val; private List<TreeNode> children; public TreeNode(int val) { this.val = val; children = new ArrayList<>(); } public void addChild(TreeNode child) { children.add(child); } public List<TreeNode> getChildren() { return children; } } ``` 如果你希望将树形结构转为list的同时保留节点的层级信息,可以使用一个helper类来记录每个节点的层级: ```java public class FlattenedTreeNode { private TreeNode node; private int level; public FlattenedTreeNode(TreeNode node, int level) { this.node = node; this.level = level; } public TreeNode getNode() { return node; } public int getLevel() { return level; } } public List<FlattenedTreeNode> flatten(TreeNode root) { List<FlattenedTreeNode> result = new ArrayList<>(); flattenHelper(root, 0, result); return result; } private void flattenHelper(TreeNode node, int level, List<FlattenedTreeNode> result) { result.add(new FlattenedTreeNode(node, level)); for (TreeNode child : node.getChildren()) { flattenHelper(child, level + 1, result); } } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值