第一步:构建实体类,包括字段id,pId,节点名称,构造方法
@Data public class PdNode extends BaseEntity { private Integer pdId; private Integer pId; private String pdName; /*存储当前节点的子节点*/ public List<PdNode> children = new ArrayList<>(); public PdNode(int pdId,int pId){ this.pdId=pdId; this.pId=pId; } public PdNode(int pdId ,int pId,String pdName){ this.pdId=pdId; this.pdName=pdName; this.pId=pId; } } 第二步:从前端获取list集合数据,并把数据丢给buildTree方法。
/*获取list数据,调用构建树方法 真接口*/ @PostMapping("/Buildtree") public List<PdNode> handleVo() { PdNode first = new PdNode(1, 0, "first"); PdNode second = new PdNode(2, 1, "second"); PdNode third = new PdNode(3, 2, "third"); PdNode four = new PdNode(4, 2, "4th"); PdNode fiver = new PdNode(5, 1, "fiver"); PdNode six = new PdNode(6, 2, "six"); List<PdNode> pdNodes = Arrays.asList(first, second, third, four, fiver, six); return buildTree(pdNodes); }
第三步:使用递归,获取树结构
3.1,过滤父id不为0的数据(除了第一层所有的子节点),将他们收集起来分组,扔到map里面,此时返回的map集合,key就是pId,value就是子节点
3.2,通过pId遍历拿到所有子节点,赋值给实体类的children属性,此时chidren里面就有所有的子对象
3.3,过滤所有的pId=0的节点,并把这些节点收集起来,返回
/*树结构逻辑1 递归的方法 */ public List<PdNode> buildTree(List<PdNode> pdNodes) { /*将这些非顶级节点的数据按pid进行分组, 这个是根据pid为key,第一步过滤非pid=0(非第一层的数据)的节点,收集所有的pid,第二步进行分组,放到map里面,key就是pid*/ Map<Integer, List<PdNode>> nodeMap = pdNodes.stream().filter(pdNode -> pdNode.getPId() != 0).collect(Collectors.groupingBy(pdNode -> pdNode.getPId())); /*循环设置对应子节点,如果pid=id,那么这个节点就是子节点,map通过get获取key值,key就是pid 把map集合里面的key赋值给pdNode的构造函数中 */ pdNodes.forEach(pdNode -> pdNode.setChildren(nodeMap.get(pdNode.getPdId()))); //获取顶级节点,过滤第一层,pid=0的节点 List<PdNode> treeNode = pdNodes.stream().filter(pdNode -> pdNode.getPId() == 0).collect(Collectors.toList()); return treeNode; }
效果
id,和pId是string类型
但是这个有个弊端,就是pId,必须锁死为0,如果是String类型,那么.equals("固定死的pId");
a.equals(b) 相反 就是 !a.equals.(b)
/*获取list数据,调用构建树方法 id和pId都是String类型 真接口2 ok的*/ @PostMapping("/BuildStringtree") public List<PdStringNode> handleStringVo() { PdStringNode first = new PdStringNode("aaaaa", "a1" ,"first"); PdStringNode second = new PdStringNode("bbbbb", "aaaaa", "second"); PdStringNode third = new PdStringNode("ccccc", "bbbbb", "third"); PdStringNode four = new PdStringNode("ddddd", "bbbbb", "4th"); PdStringNode fiver = new PdStringNode("eeeee", "aaaaa", "fiver"); PdStringNode six = new PdStringNode("fffff", "ddddd", "six"); List<PdStringNode> pdStringNodes = Arrays.asList(first, second, third, four, fiver, six); return buildStringTree(pdStringNodes); } /*树结构逻辑2 递归的方法 DFS pId为String类型 ok的,但是pid写死的*/ public List<PdStringNode> buildStringTree(List<PdStringNode> pdStringNodes) { Map<String, List<PdStringNode>> nodeMap = pdStringNodes.stream().filter(pdStringNode -> !pdStringNode.getPId().equals("a1")).collect(Collectors.groupingBy(pdStringNode -> pdStringNode.getPId())); pdStringNodes.forEach(pdStringNode -> pdStringNode.setChildren(nodeMap.get(pdStringNode.getPdId()))); //获取顶级节点,过滤第一层,pid=0的节点 List<PdStringNode> treeNode = pdStringNodes.stream().filter(pdStringNode -> pdStringNode.getPId().equals("a1")).collect(Collectors.toList()); return treeNode; }