首页 > 技术文章 > 方法的递归

minnersun 2020-08-18 19:20 原文

方法的递归

  在方法的执行过程中,调用了本方法

    java.lang.StackOverflowError:栈溢出错误,超过了栈给出的总内存

package cn.tedu.test;

public class Test2 {
    public static void main(String[] args) {
        System.out.println(sum(5));
    }
    
    //递归方法
    public static int sum(int n){
        //结束的标志    ------- 一定要有结束标志
        if(n==1){
            return 1;
        }
        return n+sum(--n);
    }
}

 案例:

A.使用递归统计工作空间有多少个.java文件和.class文件

import java.io.File;

/*
 * 统计工作空间有多少个.java文件和.class文件
 */
public class FileDemo {

    // 统计数
    static int countJava;
    static int countClass;

    public static void main(String[] args) {
        File file = new File("");
        countFile(file);
        System.out.println(".java文件个数:"+countJava);
        System.out.println(".class文件个数:"+countClass);
    }

    // 统计.java和.class文件的个数
    public static void countFile(File file) {
        // 判断是否是目录
        if (file.isDirectory()) {
            // 把目录下的信息展示
            File[] fs = file.listFiles();
            // 遍历文件数组里的内容
            for (File f : fs) {
                // 调用本方法
                countFile(f);
            }
        }else if(file.getName().endsWith(".java")){    //代码执行到这,已经是文件
            countJava++;
        }else if(file.getName().endsWith(".class")){
            countClass++;
        }
    }
}

 

 

B.使用递归的方式生成多级树案例

1.测试代码

Menu.java
package com.wiscom;
​
import java.util.List;
​
public class Menu {
    private String id;
    private String parentId;
    private String text;
    private String url;
    private String yxbz;
    private List<Menu> children;
    /*省略get\set*/
}
​
BaseApplicationTests.java
package com.wiscom;
​
import io.swagger.util.Json;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
​
import java.util.ArrayList;
import java.util.List;
​
@SpringBootTest
class BaseApplicationTests {
​
    @Test
    void contextLoads() {
        List<Menu> menuList = new ArrayList<Menu>();
        /*插入一些数据*/
        menuList.add(new Menu("GN001D000", "0", "系统管理", "/admin", "Y"));
        menuList.add(new Menu("GN001D100", "GN001D000", "权限管理", "/admin", "Y"));
        menuList.add(new Menu("GN001D110", "GN001D100", "密码修改", "/admin", "Y"));
        menuList.add(new Menu("GN001D120", "GN001D100", "新加用户", "/admin", "Y"));
        menuList.add(new Menu("GN001D200", "GN001D000", "系统监控", "/admin", "Y"));
        menuList.add(new Menu("GN001D210", "GN001D200", "在线用户", "/admin", "Y"));
        menuList.add(new Menu("GN002D000", "0", "订阅区", "/admin", "Y"));
        menuList.add(new Menu("GN003D000", "0", "未知领域", "/admin", "Y"));
        menuList.add(new Menu("GN001D300", "GN001D210", "aaaaa", "/admin", "Y"));
        menuList.add(new Menu("GN001D400", "GN001D300", "bbbb", "/admin", "Y"));
​
        /*让我们创建树*/
        MenuTree menuTree = new MenuTree(menuList);
        menuList = menuTree.builTree();
        /*转为json看看效果*/
​
        String jsonOutput = Json.pretty(menuList);
        System.out.println(jsonOutput);
    }
}
class MenuTree {
    private List<Menu> menuList = new ArrayList<Menu>();
​
    public MenuTree(List<Menu> menuList) {
        this.menuList = menuList;
    }
​
    //建立树形结构
    public List<Menu> builTree() {
        //
        List<Menu> treeMenus = new ArrayList<Menu>();
        // 遍历根节点,getRootNode():获取根节点的数据
        for (Menu menuNode : getRootNode()) {
            menuNode = buildChilTree(menuNode);
            treeMenus.add(menuNode);
        }
        return treeMenus;
    }
​
    //递归,建立子树形结构
    // pNode: 父级树的信息
    private Menu buildChilTree(Menu pNode) {
        // 用于存储父级树下子树信息
        List<Menu> chilMenus = new ArrayList<Menu>();
​
        // 遍历所有传入的数据
        for (Menu menuNode : menuList) {
            // 判断数据的父级节点是否为当前的节点
            if (menuNode.getParentId().equals(pNode.getId())) {
                // 将当前遍历的数据添加到当前pNode的孩子节点
                chilMenus.add(buildChilTree(menuNode));
            }
        }
        pNode.setChildren(chilMenus);
        return pNode;
    }
​
    //获取根节点
    private List<Menu> getRootNode() {
        List<Menu> rootMenuLists = new ArrayList<Menu>();
        // menuList:初始化MenuTree时的的数据
        for (Menu menuNode : menuList) {
            // 判断ParentId是否为0,判断是否为根节点
            if (menuNode.getParentId().equals("0")) {
                // 如果是将根节点的数据添加进list中
                rootMenuLists.add(menuNode);
            }
        }
        // 返回List<Menu>,list中包含所有根节点的数据
        return rootMenuLists;
    }
​
}

 

 

2.递归实战应用

TreeCommon.java
package com.wiscom.domain;
​
import java.util.List;
​
/**
 * @program: base
 * @description: 用于返回树的信息
 * @author: 王新晖
 * @create: 2020/05/13
 */
public class TreeCommon {
    private String id;
    private String parentId;
    private String name;
    private List<TreeCommon> children;
}
TreesController.java
package com.wiscom.controller;
​
import com.wiscom.Application;
import com.wiscom.common.ApiResult;
import com.wiscom.service.ITreesService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
​
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
​
import javax.ws.rs.core.MediaType;
​
/**
 * @program: base
 * @description: 实现系统树
 * @author: 王新晖
 * @create: 2020/5/7
 */
@Component
@Path("trees")
@Api(value = "实现系统树的接口-TreesController", description = "系统树接口")
public class TreesController {
​
    private static final Logger logger = LoggerFactory.getLogger(Application.class);
​
    @Autowired
    private ITreesService iTreesService;
​
    @GET
    @Path("getTwoDoorTree")
    @Produces(MediaType.APPLICATION_JSON)
    @ApiOperation("二道门在岗管理-二级页面的三级树- 待优化")
//    @Authorization
    public ApiResult getTwoDoorTree(
    ) {
​
        return ApiResult.Success(iTreesService.getTwoDoorTree());
    }
​
​
    @GET
    @Path("getEarlyWarningTree")
    @Produces(MediaType.APPLICATION_JSON)
    @ApiOperation("首页-应急预警数量分析-危化品二级页面三级树")
//    @Authorization
    public ApiResult getEarlyWarningTree(
    ) {
        return ApiResult.Success(iTreesService.getEarlyWarningTree());
    }
​
    @GET
    @Path("getMajorHazardSourcesTree")
    @Produces(MediaType.APPLICATION_JSON)
    @ApiOperation("重大危险源备案-一级页面四级树")
//    @Authorization
    public ApiResult getMajorHazardSourcesTree(
    ) {
​
        return ApiResult.Success(iTreesService.getMajorHazardSourcesTree());
    }
}
ITreesService.java
package com.wiscom.service;
​
import com.wiscom.domain.TreeCommon;
​
import java.util.List;
​
​
public interface ITreesService {
​
    List<TreeCommon> getTwoDoorTree();
​
    List<TreeCommon> getEarlyWarningTree();
​
    List<TreeCommon> getMajorHazardSourcesTree();
}
TreesService.java
package com.wiscom.service.impl;
​
import com.wiscom.domain.TreeCommon;
import com.wiscom.repository.TreesMapper;
import com.wiscom.service.ITreesService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
​
import java.util.*;
​
@Service
public class TreesService implements ITreesService {
    @Autowired
    TreesMapper treesMapper;
​
    // 二道门在岗管理,二级页面树,待优化
    @Override
    public List<TreeCommon> getTwoDoorTree() {
        // 查询第三级数据,二道门企业的id,name,parentId
        List<TreeCommon> thirdLevelTree = treesMapper.getTwoDoorTreeThirdLevelTree();
        // 查询第二级数据,区域的id,name,parentId
        List<TreeCommon> secondLevelTree = treesMapper.getTwoDoorTreeSecoundLevelTree();
        //查询第一级数据,市的id,name,parentId
        List<TreeCommon> firstLevelTree = treesMapper.getTwoDoorTreeFirstLevelTree();
​
        // 将查询到的所有数据整合到一起
        List<TreeCommon> allLevelTree = new ArrayList<>();
​
        // 将所有的list数据合并到thirdLevelTree中
        allLevelTree.addAll(thirdLevelTree);
        allLevelTree.addAll(secondLevelTree);
        allLevelTree.addAll(firstLevelTree);
​
        // 用于存储放回的数据
        List<TreeCommon> treeReturnInfo = new ArrayList<>();
​
        // 建立树形结构
        for (TreeCommon treeCommon : firstLevelTree) {
            // 调用递归方法,根据第一级树的信息,为其创建所有子树
            treeCommon = buildChildTree(treeCommon, allLevelTree);
            // treeReturnInfo:存储以经创建好的树,最后返回给前端
            treeReturnInfo.add(treeCommon);
        }
​
        return treeReturnInfo;
    }
​
    // 首页-应急预警数量分析-二级页面危化品树
    @Override
    public List<TreeCommon> getEarlyWarningTree() {
        // 查询第三级数据,危化品企业的id,name,parentId
        List<TreeCommon> thirdLevelTree = treesMapper.getDangerousChemicalsThirdLevelTree();
        // 查询第二级数据,区域的id,name,parentId
        List<TreeCommon> secondLevelTree = treesMapper.getDangerousChemicalSecoundLevelTree();
        //查询第一级数据,市的id,name,parentId
        List<TreeCommon> firstLevelTree = treesMapper.getDangerousChemicalFirstLevelTree();
​
        // 将查询到的所有数据整合到一起
        List<TreeCommon> allLevelTree = new ArrayList<>();
​
        // 将所有的list数据合并到thirdLevelTree中
        allLevelTree.addAll(thirdLevelTree);
        allLevelTree.addAll(secondLevelTree);
        allLevelTree.addAll(firstLevelTree);
​
        // 用于存储放回的数据
        List<TreeCommon> treeReturnInfo = new ArrayList<>();
​
        // 建立树形结构
        for (TreeCommon treeCommon : firstLevelTree) {
            // 调用递归方法,根据第一级树的信息,为其创建所有子树
            treeCommon = buildChildTree(treeCommon, allLevelTree);
            // treeReturnInfo:存储以经创建好的树,最后返回给前端
            treeReturnInfo.add(treeCommon);
        }
​
        return treeReturnInfo;
    }
​
    @Override
    public List<TreeCommon> getMajorHazardSourcesTree() {
        // 查询第四级数据,重大危险源名称的id,name,parentId
        List<TreeCommon> forthLevelTree = treesMapper.getMajorHazardSourcesForthLevelTree();
        // 查询第三级级数据,相关企业的id,name,parentId
        List<TreeCommon> thirdLevelTree = treesMapper.getMajorHazardSourcesThirdLevelTree();
        // 查询第二级级数据,相关区的id,name,parentId
        List<TreeCommon> secondLevelTree = treesMapper.getMajorHazardSourcesSecondLevelTree();
        // 查询第一级级数据,相关区的id,name,parentId
        List<TreeCommon> firstLevelTree = treesMapper.getMajorHazardSourcesFirstLevelTree();
​
        // 将查询到的所有数据整合到一起
        List<TreeCommon> allLevelTree = new ArrayList<>();
​
        // 将所有的list数据合并到thirdLevelTree中
        allLevelTree.addAll(forthLevelTree);
        allLevelTree.addAll(thirdLevelTree);
        allLevelTree.addAll(secondLevelTree);
        allLevelTree.addAll(firstLevelTree);
​
​
        // 用于存储放回的数据
        List<TreeCommon> treeReturnInfo = new ArrayList<>();
​
        // 建立树形结构
        for (TreeCommon treeCommon : firstLevelTree) {
            // 调用递归方法,根据第一级树的信息,为其创建所有子树
            treeCommon = buildChildTree(treeCommon, allLevelTree);
            // treeReturnInfo:存储以经创建好的树,最后返回给前端
            treeReturnInfo.add(treeCommon);
        }
​
        return treeReturnInfo;
    }
​
​
    // 根据一级树数据,使用递归,建立子树形结构
    // pNode:父节点的数据
    // allLevelTree:查询到的所有节点的数据
    public TreeCommon buildChildTree(TreeCommon pNode, List<TreeCommon> allLevelTree) {
​
        // 用于存储父级树下的子树数据
        List<TreeCommon> levelTree = new ArrayList<>();
​
        // 每一层遍历的allLevelTree都相同
        ArrayList<TreeCommon> alltreesInfo = new ArrayList<>();
        alltreesInfo.addAll(allLevelTree);
​
        // 遍历所有传入的数据
        for (TreeCommon index : alltreesInfo) {
            // 如果index的parentId与pNode的id相等,则index为pNode的子节点
            if (pNode.getId().equals(index.getParentId())) {
                // index为pNode的子节点,则将子节点的数据存入levelTree
                levelTree.add(buildChildTree(index, alltreesInfo));
            }
        }
        pNode.setChildren(levelTree);
        return pNode;
    }
}
TreesMapper.java
package com.wiscom.repository;
​
import com.wiscom.domain.TreeCommon;
import org.springframework.stereotype.Repository;
​
import java.util.List;
​
@Repository
public interface TreesMapper {
    // 危化品第三级树信息-企业
    List<TreeCommon> getDangerousChemicalsThirdLevelTree();
    // 危化品第二级树信息-相关区
    List<TreeCommon> getDangerousChemicalSecoundLevelTree();
    // 危化品第二级树信息-相关市
    List<TreeCommon> getDangerousChemicalFirstLevelTree();
​
    // 重大危险源备案四级树信息-相关危险源
    List<TreeCommon> getMajorHazardSourcesForthLevelTree();
    // 重大危险源备案三级树信息-相关企业
    List<TreeCommon> getMajorHazardSourcesThirdLevelTree();
    // 重大危险源备案二级树信息-相关区
    List<TreeCommon> getMajorHazardSourcesSecondLevelTree();
    // 重大危险源备案一级树信息-相关市
    List<TreeCommon> getMajorHazardSourcesFirstLevelTree();
​
    // 二道门三级树信息-相关企业
    List<TreeCommon> getTwoDoorTreeThirdLevelTree();
    // 二道门二级树信息-相关区
    List<TreeCommon> getTwoDoorTreeSecoundLevelTree();
    // 二道门一级树信息-相关市
    List<TreeCommon> getTwoDoorTreeFirstLevelTree();
}
TreesMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.wiscom.repository.TreesMapper">
    <!--危化品第三级树信息-->
    <select id="getDangerousChemicalsThirdLevelTree" resultType="com.wiscom.domain.TreeCommon">
        SELECT  cee.`AREA_CODE` id,LEFT(cee.AREA_CODE, 6) parentId, cms.`ENTERPRISE_NAME` `name`
        FROM c_mw_sensoralert cms
        INNER JOIN c_ei_enterpriseinfo cee ON cms.`ENTERPRISE_ID`=cee.`ENTERPRISE_ID`
        INNER JOIN cfg_precinct cp ON LEFT(cee.AREA_CODE, 6)=cp.`precinct_id`
        GROUP BY cms.`ENTERPRISE_ID`
    </select>
    <!--危化品第二级树信息-相关区-->
    <select id="getDangerousChemicalSecoundLevelTree" resultType="com.wiscom.domain.TreeCommon">
        SELECT LEFT(cee.AREA_CODE, 6) id,cp.`up_precinct_id` parentId,cp.`precinct_name` `name`
        FROM c_mw_sensoralert cms
        INNER JOIN c_ei_enterpriseinfo cee ON cms.`ENTERPRISE_ID`=cee.`ENTERPRISE_ID`
        INNER JOIN cfg_precinct cp ON LEFT(cee.AREA_CODE, 6)=cp.`precinct_id`
        GROUP BY cms.`ENTERPRISE_ID`
    </select>
    <!--危化品第一级树信息-相关市-->
    <select id="getDangerousChemicalFirstLevelTree" resultType="com.wiscom.domain.TreeCommon">
        SELECT cp1.`precinct_id` id,cp1.`up_precinct_id` parentId ,cp1.`precinct_name` `name`
        FROM c_mw_sensoralert cms
        INNER JOIN c_ei_enterpriseinfo cee ON cms.`ENTERPRISE_ID`=cee.`ENTERPRISE_ID`
        INNER JOIN cfg_precinct cp ON LEFT(cee.AREA_CODE, 6)=cp.`precinct_id`
        INNER JOIN cfg_precinct cp1 ON cp.`up_precinct_id`=cp1.`precinct_id`
        GROUP BY cp1.`precinct_id`
    </select>
​
​
    <!--重大危险源备案四级树信息-相关危险源-->
    <select id="getMajorHazardSourcesForthLevelTree" resultType="com.wiscom.domain.TreeCommon">
        SELECT ced.`DANGSRC_NAME` `name`,ced.`DANGSRC_ID` id,cee.`ENTERPRISE_ID` parentId
        FROM c_ei_dangsrc ced
        INNER JOIN c_ei_enterpriseinfo cee ON ced.`ENTERPRISE_ID`=cee.`ENTERPRISE_ID`
    </select><!--重大危险源备案三级树信息-相关企业-->
    <select id="getMajorHazardSourcesThirdLevelTree" resultType="com.wiscom.domain.TreeCommon">
        SELECT cee.`ENTERPRISE_ID` id,cee.`ENTERPRISE_NAME` `name`,cp.`precinct_id` parentId
        FROM c_ei_dangsrc ced
        INNER JOIN c_ei_enterpriseinfo cee ON ced.`ENTERPRISE_ID`=cee.`ENTERPRISE_ID`
        INNER JOIN cfg_precinct cp ON LEFT(cee.AREA_CODE, 6)=cp.`precinct_id`
    </select><!--重大危险源备案二级树信息-相关区-->
    <select id="getMajorHazardSourcesSecondLevelTree" resultType="com.wiscom.domain.TreeCommon">
        SELECT cp.`precinct_id` id ,cp.`precinct_name` `name`,cp1.`precinct_id` parentId
        FROM c_ei_dangsrc ced
        INNER JOIN c_ei_enterpriseinfo cee ON ced.`ENTERPRISE_ID`=cee.`ENTERPRISE_ID`
        INNER JOIN cfg_precinct cp ON LEFT(cee.AREA_CODE, 6)=cp.`precinct_id`
        INNER JOIN cfg_precinct cp1 ON cp.up_precinct_id=cp1.precinct_id
    </select><!--重大危险源备案一级树信息-相关市-->
    <select id="getMajorHazardSourcesFirstLevelTree" resultType="com.wiscom.domain.TreeCommon">
        SELECT cp1.`precinct_id` id,cp1.`precinct_name` `name`, cp2.`precinct_id` parentId
        FROM c_ei_dangsrc ced
        INNER JOIN c_ei_enterpriseinfo cee ON ced.`ENTERPRISE_ID`=cee.`ENTERPRISE_ID`
        INNER JOIN cfg_precinct cp ON LEFT(cee.AREA_CODE, 6)=cp.`precinct_id`
        INNER JOIN cfg_precinct cp1 ON cp.up_precinct_id=cp1.precinct_id
        INNER JOIN cfg_precinct cp2 ON cp1.up_precinct_id=cp2.precinct_id
        GROUP BY cp1.`precinct_id`
    </select><!--二道门三级树信息-相关企业-->
    <select id="getTwoDoorTreeThirdLevelTree" resultType="com.wiscom.domain.TreeCommon">
        SELECT cp.`precinct_id` id, cp.`precinct_name` `name`,cp.`up_precinct_id` parentId
        FROM cfg_precinct_twodoor cpt
        INNER JOIN cfg_precinct cp ON cpt.`up_precinct_id` = cp.`precinct_id`
        WHERE exist_twodoor=1
    </select><!--二道门二级树信息-相关区-->
    <select id="getTwoDoorTreeSecoundLevelTree" resultType="com.wiscom.domain.TreeCommon">
        SELECT cp1.`precinct_id` id,cp1.`precinct_name` `name`,cp1.`up_precinct_id` parentId
        FROM cfg_precinct_twodoor cpt
        INNER JOIN cfg_precinct cp ON cpt.`up_precinct_id` = cp.`precinct_id`
        INNER JOIN cfg_precinct cp1 ON cp.`up_precinct_id` = cp1.`precinct_id`
        WHERE exist_twodoor=1
    </select><!--二道门一级树信息-相关市-->
    <select id="getTwoDoorTreeFirstLevelTree" resultType="com.wiscom.domain.TreeCommon">
        SELECT cp2.`precinct_id` id,cp2.`precinct_name` `name`,cp2.`up_precinct_id` parentId
        FROM cfg_precinct_twodoor cpt
        INNER JOIN cfg_precinct cp ON cpt.`up_precinct_id` = cp.`precinct_id`
        INNER JOIN cfg_precinct cp1 ON cp.`up_precinct_id` = cp1.`precinct_id`
        INNER JOIN cfg_precinct cp2 ON cp1.`up_precinct_id` = cp2.`precinct_id`
        WHERE exist_twodoor=1
        GROUP BY cp2.precinct_id
    </select>
</mapper>

 

 

3.将递归树改为循环树

由于应急预警树出现栈溢出错误,且树的层级确定,故可以将应急预警递归树改为循环树

package com.wiscom.service.impl;
​
import com.wiscom.domain.TreeCommon;
import com.wiscom.repository.TreesMapper;
import com.wiscom.service.ITreesService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
​
import java.util.*;
​
@Service
public class TreesService implements ITreesService {
    @Autowired
    TreesMapper treesMapper;
​
​
    // 首页-应急预警数量分析-二级页面危化品树
    @Override
    public List<TreeCommon> getEarlyWarningTree() {
        // 查询第三级数据,危化品企业的id,name,parentId
        List<TreeCommon> thirdLevelTree = treesMapper.getDangerousChemicalsThirdLevelTree();
        // 查询第二级数据,区域的id,name,parentId
        List<TreeCommon> secondLevelTree = treesMapper.getDangerousChemicalSecoundLevelTree();
        //查询第一级数据,市的id,name,parentId
        List<TreeCommon> firstLevelTree = treesMapper.getDangerousChemicalFirstLevelTree();
​
        // 用于存储放回的数据
return buildChildTree(firstLevelTree, secondLevelTree, thirdLevelTree);
    }
​
    // 首页-应急预警数量分析-二级页面危化品树common
    // first:第一级树
    // second:第二级树信息
    // third:第三级树信息
    public List<TreeCommon> buildChildTree(List<TreeCommon> first, List<TreeCommon> second,List<TreeCommon> third) {
​
        // 存一级节点的数据
        List<TreeCommon> commonFirst = new ArrayList<>();
​
​
        // 存第二级遍历的数据
        // 遍历所有传入的数据
        for (TreeCommon firstTree : first) {
​
            // 存第二级遍历的数据
            List<TreeCommon> commonsSecond = new ArrayList<>();
​
            for (TreeCommon secondTree : second){
​
                // 存第三级遍历的数据
                List<TreeCommon> commonsThird = new ArrayList<>();
​
                // 将所有匹配当前第二级的数据存入commonsThird中
                for (TreeCommon thirdTree : third){
                    if (secondTree.getId().equals(thirdTree.getParentId())) {
                        commonsThird.add(thirdTree);
                        System.out.println();
                    }
                }
                // 如果commonsThird不为空,则表示,该二级节点下有数据,将数据存入二级节点
                    secondTree.setChildren(commonsThird);
​
                if (secondTree.getParentId().equals(firstTree.getId())){
                    // 将当前节点存入commonsSecond中
                    commonsSecond.add(secondTree);
                }
​
                // 将二级节点的list存入一级节点的子节点中
                firstTree.setChildren(commonsSecond);
            }
            commonFirst.add(firstTree);
            System.out.println();
​
        }
​
        return commonFirst;
    }
}

 

4.优化递归树

  不再是固定层数的递归树,控制递归树的层数,以防内存溢出

package com.wiscom.service.impl;

import com.wiscom.repository.TreeMapper;
import com.wiscom.service.ITreeService;
import com.wiscom.vo.HazardSourceTreeVO;
import com.wiscom.vo.TreeVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

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

/**
 * @Program:
 * @Description:
 * @Author:Lgd
 * @Date:2020/8/27 20:25
 */

@Service
public class TreeService implements ITreeService {

    @Autowired
    private TreeMapper treeMapper;
    
    /**
     *   递归实现树
     */
    @Override
    public List<HazardSourceTreeVO> queryHazardSourceTree() {
        List<TreeVO> treeVOList = treeMapper.getTree();
        int count = 0;
        int count1 = 0;

        List<HazardSourceTreeVO> children1 = new ArrayList<>();
        for (int i = 0; i < treeVOList.size(); i++) {
            //第一层  南京市
            if ("320000".equals(treeVOList.get(i).getParentId())) {
                HazardSourceTreeVO hazardSourceTreeVO1 = new HazardSourceTreeVO();
                hazardSourceTreeVO1.setId(treeVOList.get(i).getId());
                hazardSourceTreeVO1.setName(treeVOList.get(i).getName());
                hazardSourceTreeVO1.setParentId(treeVOList.get(i).getParentId());
                children1.add(hazardSourceTreeVO1);
                //递归南京市以下的每一层数据
                this.createTree(treeVOList, hazardSourceTreeVO1, count);
            }
        }
        //递归方式,清除不含重大危险源的辖区及企业信息
        this.cleanNode(children1, count1);
        return children1;
    }

    //递归生成树
    public void createTree(List<TreeVO> treeVOList, HazardSourceTreeVO hazardSourceTreeVO1, int cycle) {
        cycle++;
        //递归10层
        if (cycle > 10) {
            return;
        }
        //生成树的递归方法主体
        List<HazardSourceTreeVO> children2 = new ArrayList<>();
        for (int j = 0; j < treeVOList.size(); j++) {
            if (hazardSourceTreeVO1.getId().equals(treeVOList.get(j).getParentId())) {
                HazardSourceTreeVO hazardSourceTreeVO2 = new HazardSourceTreeVO();
                hazardSourceTreeVO2.setId(treeVOList.get(j).getId());
                hazardSourceTreeVO2.setName(treeVOList.get(j).getName());
                hazardSourceTreeVO2.setParentId(treeVOList.get(j).getParentId());
                children2.add(hazardSourceTreeVO2);
                hazardSourceTreeVO1.setChildren(children2);
                int cycleCount = cycle;
                createTree(treeVOList, hazardSourceTreeVO2, cycleCount);
            }
        }
    }

    //递归清除不含重大危险源的辖区及企业信息
    public void cleanNode(List<HazardSourceTreeVO> children1, int cycle1) {
        cycle1++;
        //清除3层
        if (cycle1 > 3) {
            return;
        }
        //清除空节点的递归方法主体
        for (int i = children1.size() - 1; i >= 0; i--) {
            if (children1.get(i).getChildren() == null) {
                children1.remove(i);
            } else {
                List<HazardSourceTreeVO> children2 = children1.get(i).getChildren();
                int count1 = cycle1;
                cleanNode(children2, count1);
            }
        }
    }
}

 

推荐阅读