List转树,寻找树的所有叶子路径

需求

最近公司有一个需求,总结下来就是一个扁平List转成树,然后获取到树的所有路径。

下面是需求抽象出的部分实体类和部分字段

@Data
public class FormTopic {

    private Integer topicId;//当前节点id

    private Integer parentId;//父id

    private String topicName;//节点名

    private List<FormTopic> children;//所有子节点

    public FormTopic(Integer topicId, Integer parentId, String topicName) {
        this.topicId = topicId;
        this.parentId = parentId;
        this.topicName = topicName;
    }
}

    /**
     * 模拟DAO层从数据库查到的数据
     */
    private static List<FormTopic> getFormTopics(){
        List<FormTopic> topics = new ArrayList<>();

        FormTopic formTopic = new FormTopic(1,-1,"A");
        FormTopic formTopic2 = new FormTopic(2,-1,"B");
        FormTopic formTopic3 = new FormTopic(3,1,"C");
        FormTopic formTopic4 = new FormTopic(4,1,"D");
        FormTopic formTopic5 = new FormTopic(5,3,"E");
        FormTopic formTopic6 = new FormTopic(6,5,"F");
        FormTopic formTopic7 = new FormTopic(7,2,"G");
        FormTopic formTopic8 = new FormTopic(8,2,"H");
        FormTopic formTopic9 = new FormTopic(9,7,"I");
        FormTopic formTopic10 = new FormTopic(10,3,"J");
        FormTopic formTopic11 = new FormTopic(11,2,"K");
        topics.add(formTopic);
        topics.add(formTopic2);
        topics.add(formTopic3);
        topics.add(formTopic4);
        topics.add(formTopic5);
        topics.add(formTopic6);
        topics.add(formTopic7);
        topics.add(formTopic8);
        topics.add(formTopic9);
        topics.add(formTopic10);
        topics.add(formTopic11);
        return topics;
    }

如图所示:

image-20210105221257551

下面用java实现:

public static void main(String[] args) {
        List<FormTopic> formTopics = getFormTopics();
        List<FormTopic> trees = convertToTree(formTopics);
        List<LinkedList<FormTopic>> allPath = depthFirstTraversal(trees);
        System.out.println("============");
    }

    /**
     * 删除冗余树节点
     */
    private static void clearSurplusNode(List<LinkedList<FormTopic>> allPath) {
        Set<Integer> set = new HashSet<>();
        for(List<FormTopic> topics : allPath){
            for (FormTopic topic : topics) {
                if(!set.contains(topic.getTopicId()) && topic.getChildren()!=null){
                    topic.setChildren(null);
                    set.add(topic.getTopicId());
                }
            }
        }
    }


    /**
     *递归形式的深度优先遍历
     */
    private static List<LinkedList<FormTopic>> depthFirstTraversal(List<FormTopic> trees) {
        List<LinkedList<FormTopic>> result = new ArrayList<>();

        for(FormTopic tree : trees){
            LinkedList<FormTopic> path = new LinkedList<>();
            path.add(tree);
            findPath(result, tree, path);
        }
        clearSurplusNode(result);
        return result;
    }

    private static void findPath(List<LinkedList<FormTopic>> result, FormTopic tree, LinkedList<FormTopic> path) {
        List<FormTopic> children = tree.getChildren();
        if (children == null || children.size() <= 0) {
            result.add(path);
            return;
        }
        for (FormTopic child : children) {
            LinkedList<FormTopic> cPath = new LinkedList<>(path);
            cPath.add(child);
            findPath(result, child, cPath);
        }
    }

    private static List<FormTopic> convertToTree(List<FormTopic> formTopics) {
        List<FormTopic> roots = formTopics.stream().filter(t -> t.getParentId() == -1).collect(Collectors.toList());
        return toTree(roots, formTopics);
    }

    //转成树
    private static List<FormTopic>  toTree(List<FormTopic> roots, List<FormTopic> formTopics) {
        return roots.stream().peek(topic -> {
            List<FormTopic> children = formTopics.stream().filter(t -> topic.getTopicId().equals(t.getParentId())).collect(Collectors.toList());
            toTree(children, formTopics);
            topic.setChildren(children);
        }).collect(Collectors.toList());
    }

断点:

image-20210105221907039

以上代码就实现了上述需求(可能非最优解,勿喷)

原文地址:https://www.cnblogs.com/wwjj4811/p/14238419.html