Java递归获取省市区树形结构

递归

简单地说,就是如果在函数中存在着调用函数本身的情况,这种现象就叫递归;而在实际开发中,常见的递归使用场景有省市区父子级数据获取,树形菜单等。现在,我以Java递归获取省市区来实战一遍递归的使用场景

实现省市区树形数据展示

具体最终数据展示:
在这里插入图片描述
为了方便演示,不采用MySQL查询数据库,本地模拟省市区数据即可

  • 区域类
import lombok.Data;

/**
 * @Description
 * @Author Fangchenjiang
 * @Date 2021/8/19 16:24
 */
@Data
public class Region {
    /**
     * id
     */
    private Integer id;

    /**
     * 区域名称
     */
    private String areaName;


    /**
     * 区域类型:1-省区 2-市区,3-片区
     */
    private Integer type;

    /**
     * 上级id
     */
    private Integer superId;

    public Region(Integer id, String areaName, Integer type, Integer superId) {
        this.id = id;
        this.areaName = areaName;
        this.type = type;
        this.superId = superId;
    }
}
  • 展示数据VO类
/**
 * @Description
 * @Author Fangchenjiang
 * @Date 2021/8/19 16:36
 */
@Data
public class RegionTree {
    /**
     * id
     */
    private Integer id;

    /**
     * 区域名称
     */
    private String name;

    /**
     * 子节点
     */
    private List<RegionTree>treeChild;
}
  • Demo演示
/**
 * @Description
 * @Author Fangchenjiang
 * @Date 2021/8/19 16:49
 */
public class MainTest {
    public static void main(String[] args) {
        List<Region> allRegion = getAllRegion();
        List<RegionTree> regionTreeList = buildTree(allRegion, null, 3);
        System.out.println(JSONObject.toJSONString(regionTreeList));

    }

    /**
     * 构造父子级
     *
     * @param allRegion
     * @param pid
     * @return
     */
    private static List<RegionTree> buildTree(List<Region> allRegion, Integer pid, Integer type) {
        
        List<RegionTree> regionTreeList = new ArrayList<>();
        //获取省
        if (type.equals(1)) {
            List<Region> regionList = allRegion.stream().filter(region -> region.getType().equals(1)).collect(Collectors.toList());
            for (Region region : regionList) {
                RegionTree regionTree = new RegionTree();
                regionTree.setId(region.getId());
                regionTree.setName(region.getAreaName());
                regionTreeList.add(regionTree);
            }
        } else if (type.equals(2)) {
            //获取省市
            List<Region> regionList = allRegion.stream().filter(region -> region.getType().equals(1) || region.getType().equals(2)).collect(Collectors.toList());
            for (Region region : regionList) {
                RegionTree regionTree = new RegionTree();
                if (Objects.equals(pid, region.getSuperId())) {
                    regionTree.setId(region.getId());
                    regionTree.setName(region.getAreaName());
                    regionTree.setTreeChild(buildTree(allRegion, region.getId(), type));
                    regionTreeList.add(regionTree);
                }
            }

        } else {
            //获取省市区
            for (Region region : allRegion) {
                RegionTree regionTree = new RegionTree();
                if (Objects.equals(pid, region.getSuperId())) {
                    regionTree.setId(region.getId());
                    regionTree.setName(region.getAreaName());
                    regionTree.setTreeChild(buildTree(allRegion, region.getId(), type));
                    regionTreeList.add(regionTree);
                }
            }
        }
        return regionTreeList;
    }

    /**
     * 获取总数据
     *
     * @return
     */
    public static List<Region> getAllRegion() {
        List<Region> regionList = new ArrayList<>();
        regionList.add(new Region(1, "贵州省", 1, null));
        regionList.add(new Region(11, "贵阳市", 2, 1));
        regionList.add(new Region(12, "遵义市", 2, 1));
        regionList.add(new Region(111, "观山湖区", 3, 11));
        regionList.add(new Region(112, "花溪区", 3, 11));
        regionList.add(new Region(121, "牡丹区", 3, 12));
        regionList.add(new Region(122, "红花岗区", 3, 12));
        regionList.add(new Region(2, "广东省", 1, null));
        regionList.add(new Region(21, "广州市", 2, 2));
        regionList.add(new Region(211, "天河区", 3, 21));
        return regionList;
    }
}

总结

递归不难理解,重点要注意省市区直接的联系,比如superId父级作为切入点,另外核心注意VO展示类的构造以及递归函数buildTree的使用;同理,如果遇到获取树形菜单,我们也可以依葫芦画瓢即可实现类似功能。

/** * 根据等级查询类目 * * @param level * @return */ @Override public List queryCategoryTree(Integer level) { //查询当前级别下类目 List list = categoryDAO.list(level); //组装好的类目,返回前端 List categoryTree = new ArrayList(); //所有类目 List allDTOList = new ArrayList(); if (CollectionUtils.isEmpty(list)) { return categoryTree; } for (CategoryDO categoryDO : list) { allDTOList.add(new CategoryTreeDTO().convertDOToDTO(categoryDO)); } //当前等级类目 categoryTree = allDTOList.stream().filter(dto -> level.equals(dto.getLevel())).collect(Collectors.toList()); for (CategoryTreeDTO categoryTreeDTO : categoryTree) { //组装类目为结构 assembleTree(categoryTreeDTO, allDTOList,Constants.CATEGORY_MAX_LEVEL - level); } return categoryTree; } /** * 组装 * * @param categoryTreeDTO * @param allList * @param remainRecursionCount 剩余递归次数 * @return */ public CategoryTreeDTO assembleTree(CategoryTreeDTO categoryTreeDTO, List allList, int remainRecursionCount) { remainRecursionCount--; //最大递归次数不超过Constants.CATEGORY_MAX_LEVEL-level次,防止坏数据死循环 if(remainRecursionCount < 0){ return categoryTreeDTO; } String categoryCode = categoryTreeDTO.getCategoryCode(); Integer level = categoryTreeDTO.getLevel(); //到达最后等级返回 if (Constants.CATEGORY_MAX_LEVEL == level) { return categoryTreeDTO; } //子类目 List child = allList.stream().filter(a -> categoryCode.equals(a.getParentCode())).collect(Collectors.toList()); if (null == child) { return categoryTreeDTO; } categoryTreeDTO.setChildren(child); //组装子类目 for (CategoryTreeDTO dto : child) { assembleTree(dto, allList,remainRecursionCount); } return categoryTreeDTO; }
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值