java实现Tree树结构,递归方式(只存在父子关系)

java实现Tree树结构,递归方式(只存在父子关系)

- 6个基础表(图1-1)
- 两两之间父子关系(图1-2)
- id会重复,同理pid也会重复(代码1-1)

图1-1:
在这里插入图片描述

图1-2:
在这里插入图片描述

难点:

  1. 不在同一个表,父子关系只存在于相邻表中,导致很难建立树形关系

  2. 操作6个不同的javaBean,表结构有所不同,如何递归处理

  3. 递归关系一般是由一个表中的id与pid的子父关系,通过递归循环本集合,以实现tree结构,一个pid只能代表一个含义,但现在6个表中都有可能出现pid=1的情况,但id=1代表的含义有可能是科、属、目或别的类型的id=1

解决方法:

  1. 如果想要通过循环遍历,未免代码量太多,且不便于读取,并且执行效率底下,但如果想通过递归实现Tree树,需要根据pid关联上级,直到不能再细分便是递归出口,但pid会因为6个表出现重复的id,导致无法识别是否是上级的pid

  2. 所以不可以将6个entity集合合并去递归,那么想要递归却有6个entity集合,如何区分何时应该递归,出口应该如何定制,答案其实很简单,就是当循环完一层后设当前层循环数据为空,下次递归进来便因非空判断执行下一层,直到递归到最后一层 “属”,不再递归开始return,便有了出口

  3. 如何保证每次都是上下两级id与pid相互映射?那么就是循环本层分支带着上层的id与本层的pid比较

遇到的问题:

  1. 结果集每次每层只有一个树,原因是在循环中Childs用的是add,一定要注意修改为addAll,并且返回树集合
  2. 前端点击问题:设想如果用户点击某一层,需要做响应操作,传输的id如何利用正确的层查询或做不同的操作呢?(例如,科id=1 name = “犬科” 目id=1 name = “鬼笔目”,我怎么知道点的是哪一层?因为只给了后端一个id,且前端也只能给个id。最后根据业务确定只要调用接口,必然是"属"调用,可以完美避免这个问题,那么如果这个需求必须实现,思路如何呢?)
    思路:可以在递归时给对象中添加一个属性,如type=1,表示科,前端传输每次传type与id,即可区分是哪层的哪个id做的点击事件

代码部分:

@Override
	public Result treeList() {
		List<SpeciKingdom> kingdoms = speciKingdomMapper.selectList(new QueryWrapper<>());
		List<SpeciPhylum> speciPhylums = speciPhylumMapper.selectList(new QueryWrapper<>());
		List<SpeciClass> speciClasses = speciClassMapper.selectList(new QueryWrapper<>());
		List<SpeciOrder> speciOrders = speciOrderMapper.selectList(new QueryWrapper<>());
		List<SpeciFamily> speciFamilies = speciFamilyMapper.selectList(new QueryWrapper<>());
		List<SpeciGenus> speciGenus = speciGenusMapper.selectList(new QueryWrapper<>());

		ArrayList<TreeEntity> treeList = new ArrayList<>();

		kingdoms.forEach(x ->{
			TreeEntity treeEntity = new TreeEntity();
			treeEntity.setChilds(Lists.newArrayList());
			treeEntity.setId(x.getSkId());
			treeEntity.setName(x.getSkName());
			TreeEntityTemp temp = findSub(x.getSkId(), speciPhylums, speciClasses, speciOrders, speciFamilies, speciGenus);
			treeEntity.getChilds().addAll(temp.getChilds());
			treeEntity.setChildsNum(temp.getChildsNum());
			treeList.add(treeEntity);
		});
		Result result = Result.ok();
		result.setData(treeList);
		return result;
	}

	public TreeEntityTemp findSub(Integer id, List<SpeciPhylum> speciPhylums, List<SpeciClass> speciClasses,
							  List<SpeciOrder> speciOrders, List<SpeciFamily> speciFamilies, List<SpeciGenus> speciGenus){
		TreeEntityTemp temp = new TreeEntityTemp();
		ArrayList<TreeEntity> list = new ArrayList<>();
		if(speciPhylums != null){
			speciPhylums.forEach( x ->{
				if(x.getSpPid() != null && id.equals(Integer.valueOf(x.getSpPid()))){
					TreeEntity entity = new TreeEntity();
					if(entity.getChilds() == null){
						entity.setChilds(Lists.newArrayList());
					}
					entity.setId(x.getSpId());
					entity.setName(x.getSpName());
					TreeEntityTemp sub = findSub(entity.getId(), null, speciClasses, speciOrders, speciFamilies, speciGenus);
					entity.getChilds().addAll(sub.getChilds());
					entity.setChildsNum(sub.getChildsNum());
					list.add(entity);
				}
			});
			temp.setChilds(list);
			temp.setChildsNum(list.size());
			return temp;
		}

		if(speciClasses != null){
			speciClasses.forEach( x ->{
				if(x.getScPid() != null && id.equals(Integer.valueOf(x.getScPid()))){
					TreeEntity entity = new TreeEntity();
					if(entity.getChilds() == null){
						entity.setChilds(Lists.newArrayList());
					}
					entity.setId(x.getScId());
					entity.setName(x.getScName());
					TreeEntityTemp sub = findSub(entity.getId(), null, null, speciOrders, speciFamilies, speciGenus);
					entity.getChilds().addAll(sub.getChilds());
					entity.setChildsNum(sub.getChildsNum());
					list.add(entity);
				}
			});
			temp.setChilds(list);
			temp.setChildsNum(list.size());
			return temp;
		}

		if(speciOrders != null){
			speciOrders.forEach( x ->{
				if(x.getSoPid() != null && id.equals(Integer.valueOf(x.getSoPid()))){
					TreeEntity entity = new TreeEntity();
					if(entity.getChilds() == null){
						entity.setChilds(Lists.newArrayList());
					}
					entity.setId(x.getSoId());
					entity.setName(x.getSoName());
					TreeEntityTemp sub = findSub(entity.getId(), null, null, null, speciFamilies, speciGenus);
					entity.getChilds().addAll(sub.getChilds());
					entity.setChildsNum(sub.getChildsNum());
					list.add(entity);
				}
			});
			temp.setChilds(list);
			temp.setChildsNum(list.size());
			return temp;
		}

		if(speciFamilies != null){
			speciFamilies.forEach( x ->{
				if(x.getSfPid() != null && id.equals(Integer.valueOf(x.getSfPid()))){
					TreeEntity entity = new TreeEntity();
					if(entity.getChilds() == null){
						entity.setChilds(Lists.newArrayList());
					}
					entity.setId(x.getSfId());
					entity.setName(x.getSfName());
					TreeEntityTemp sub = findSub(entity.getId(), null, null, null, null, speciGenus);
					entity.getChilds().addAll(sub.getChilds());
					entity.setChildsNum(sub.getChildsNum());
					list.add(entity);
				}
			});
			temp.setChilds(list);
			temp.setChildsNum(list.size());
			return temp;
		}

		if(speciGenus != null){
			speciGenus.forEach( x ->{
				if(x.getSgPid() != null && id.equals(Integer.valueOf(x.getSgPid()))){
					TreeEntity entity = new TreeEntity();
					if(entity.getChilds() == null){
						entity.setChilds(Lists.newArrayList());
					}
					entity.setId(x.getSgPid());
					entity.setName(x.getSgName());
					list.add(entity);
				}
			});
			temp.setChilds(list);
			temp.setChildsNum(list.size());
			return temp;
		}
		System.out.println("========================end==================================");
		return null;
	}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
/** * 根据等级查询类目 * * @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; }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

汪汪牛仔

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值