文章目录

  • 递归实现
  • 一、普通递归
  • 二、jdk8 stream递归
  • 总结
  • 补充
  • 简单解释下



递归实现

递归,顾名思义,自己调用自己,在java开发中,多用于构造类似菜单等业务数据的树形结构,层层嵌套;


一、普通递归

测试方法

@Test
    void treelist() {
        List<Tree> trees = initList(); // 模拟获取数据
        List<Tree> list = getTrees("0", trees);
        root.setList(list);
        System.out.println(JSONUtil.toJsonPrettyStr(root));
    }

initList

private List<Tree> initList() {
        List<Tree> trees = new ArrayList<>();
        trees.add(new Tree("0", "root"));
        trees.add(new Tree("2", "0"));
        trees.add(new Tree("6", "2"));
        trees.add(new Tree("7", "6"));
        trees.add(new Tree("3", "1"));
        trees.add(new Tree("4", "1"));
        trees.add(new Tree("5", "4"));
        trees.add(new Tree("7", "6"));
        trees.add(new Tree("5", "4"));
        trees.add(new Tree("1", "0"));
        return trees;
    }

Tree

@Data
public class Tree  {
    String id;
    String pid;
    List<Tree> list;

    public Tree(String id, String pid) {
        this.id = id;
        this.pid = pid;
    }

    public Tree() {
    }
    }

getTrees 方法

// 递归为树
    private List<Tree> getTrees(String id, List<Tree> trees) {
        List<Tree> list = new ArrayList<>();

        for (Tree tree : trees) {
            if (tree.getPid().equals(id)) {
                tree.setList(getTrees(tree.getId(), trees));
                list.add(tree);
            }
        }
        return list;
    }

二、jdk8 stream递归

@Test
    void treelist() {
        List<Tree> trees = initList();
        Tree root = trees.stream().filter(tree -> tree.getId().equalsIgnoreCase("0")).collect(toList()).get(0);
        List<Tree> childrenStream = getChildrenStream(root,trees);
        root.setList(childrenStream);
        System.out.println(JSONUtil.toJsonPrettyStr(root));
    }

实体类和上述一样
getChildrenStream 方法

private List<Tree> getChildrenStream(Tree root, List<Tree> trees) {
       return trees.stream().filter(tree -> tree.getPid().equalsIgnoreCase(root.getId())) // 返回root 的子节点
                .peek(tree -> tree.setList(getChildrenStream(tree,trees))).collect(Collectors.toList()); // peek 设置当前节点的子节点
    }

总结

两种方法对比,当然java8 效率更高,代码更简洁

快来试试 java8的stream流式递归_Test


快来试试 java8的stream流式递归_数据结构_02

补充

今天用到了删除功能,也就是递归删除,那么就需要递归找到所有集合,也就是递归寻找数据,返回集合,直接开干

@Test
    void treeListStream() {
        List<Tree> trees = initList();
        Tree root = trees.stream().filter(tree -> tree.getId().equalsIgnoreCase("0")).collect(toList()).get(0);
        List<Tree> childrenStream = CollectionUtil.newArrayList();
        getChildrenList(root, trees, childrenStream);

        System.out.println(JSONUtil.toJsonPrettyStr(childrenStream));
    }

    private List<Tree> getChildrenList(Tree root, List<Tree> trees, List<Tree> childrenStream) {
        List<Tree> collect = trees.stream().filter(tree  -> tree.getPid().equals(root.getId()))
                .peek(tree -> getChildrenList(tree, trees, childrenStream))
                .collect(toList());
        childrenStream.addAll(collect);
        return collect;
    }

简单解释下

1 childrenStream 用来装每次递归找到的子集
2 .peek 以当前找到的子节点为父节点 再次递归调用方法,寻找子集,然后也被放入了childrenStream 集合中;