Java实现多层级目录树

Java实现多层级目录树

实现思路

1.将节点数据集合按父id分组,分组结果用Map存储
2.遍历集合,用id匹配Map的key值。若查到数据则说明Map的Value值是当前节点数据的子集合

实现代码

1. 使用Node模拟实际数据

其中id为自身id,pId为父id,children为Node子集合


import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.ArrayList;
import java.util.List;

@Data
@NoArgsConstructor
public class Node {
    private Integer id;
    private Integer pId;
    private List<Node> children = new ArrayList<>();

    public Node(Integer id, Integer pId) {
        this.id = id;
        this.pId = pId;
    }
}


```java

2. 实现方法

    List<Node> getTrees(List<Node> nodes) {
        // 根据pid分组
        Map<Integer, List<Node>> nodeMap = new HashMap<>();
        for (Node node : nodes) {
            Integer pId = node.getPId();
            if (pId != null) {
                List<Node> nodeList = nodeMap.get(pId);
                if (nodeList == null) {
                    List<Node> newNodes = new ArrayList<>();
                    newNodes.add(node);
                    nodeMap.put(pId, newNodes);
                } else {
                    nodeList.add(node);
                }
            }
        }
        for (Node node : nodes) {
            List<Node> childList = nodeMap.get(node.getId());
            if (childList != null) {
                node.getChildren().addAll(childList);
            }
        }
        return nodes;
    }

3.方法测试

    public static void main(String[] args) {
        List<Node> nodes = getNodes();
        System.out.println(nodes);
        List<Node> trees = getTrees(nodes);
        System.out.println("---------------------------------------");
        System.err.println(trees);
    }

    static List<Node> getNodes() {
        List<Node> nodeList = new ArrayList<>();
        Node node1 = new Node(1, null);
        Node node2 = new Node(2, 1);
        Node node3 = new Node(3, 2);
        Node node4 = new Node(4, 2);
        Node node5 = new Node(5, 3);
        Node node6 = new Node(6, 5);
        Node node7 = new Node(7, 4);
        Node node8 = new Node(8, 5);
        nodeList.add(node1);
        nodeList.add(node2);
        nodeList.add(node3);
        nodeList.add(node4);
        nodeList.add(node5);
        nodeList.add(node6);
        nodeList.add(node7);
        nodeList.add(node8);
        return nodeList;
    }

测试结果

白色部分为原始数据,红色为N级树数据
在这里插入图片描述

代码优化

将分组过程用stream流实现

    List<Node> getTrees(List<Node> nodes) {
        Map<Integer, List<Node>> nodeMap = nodes.stream().filter(node -> node.getPId() != null).collect(Collectors.groupingBy(Node::getPId, Collectors.toList()));
        for (Node node : nodes) {
            List<Node> childList = nodeMap.get(node.getId());
            if (CollectionUtils.isNotEmpty(childList)) {
                node.getChildren().addAll(childList);
            }
        }
        return nodes;
    }

泛型化

将参数用泛型代替适用于多元化场景

package utils;

import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 树形化数据
 */
public class TreeListUtil {
    /**
     *
     * @param nodes 要树形化的数据
     * @param getId 获取节点id的方法
     * @param getPid 获取节点父id的方法
     * @param getChildren 获取子集合的方法
     * @param <Node> 节点数据
     * @param <Id> id的数据类型
     * @param <Pid> Pid的数据类型
     * @return 树形化后的数据
     */
    public static <Node, Id, Pid> List<Node> getTreeList(List<Node> nodes, Function<Node, Id> getId, Function<Node, Pid> getPid, Function<Node, List<Node>> getChildren) {
        Map<Pid, List<Node>> nodeMap = nodes.stream().filter(node -> getPid.apply(node) != null).collect(Collectors.groupingBy(getPid, Collectors.toList()));

        for (Node node : nodes) {
            List<Node> nodeList = nodeMap.get(getId.apply(node));
            if (nodeList != null) {
                getChildren.apply(node).addAll(nodeList);
            }
        }
        return nodes;
    }
}

泛型方法测试

    public static void main(String[] args) {
        List<Node> nodes = getNodes();
        System.out.println(nodes);
        System.out.println("---------------------------------------");
        // 泛型方法调用
        List<Node> treeList = TreeListUtil.getTreeList(nodes, Node::getId, Node::getPId, Node::getChildren);
        System.err.println(treeList);
    }

    static List<Node> getNodes() {
        List<Node> nodeList = new ArrayList<>();
        Node node1 = new Node(1, null);
        Node node2 = new Node(2, 1);
        Node node3 = new Node(3, 2);
        Node node4 = new Node(4, 2);
        Node node5 = new Node(5, 3);
        Node node6 = new Node(6, 5);
        Node node7 = new Node(7, 4);
        Node node8 = new Node(8, 5);
        nodeList.add(node1);
        nodeList.add(node2);
        nodeList.add(node3);
        nodeList.add(node4);
        nodeList.add(node5);
        nodeList.add(node6);
        nodeList.add(node7);
        nodeList.add(node8);
        return nodeList;
    }
测试结果

在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值