java实现Tree树结构,递归方式(只存在父子关系)
- 6个基础表(图1-1)
- 两两之间父子关系(图1-2)
- id会重复,同理pid也会重复(代码1-1)
图1-1:
图1-2:
难点:
-
不在同一个表,父子关系只存在于相邻表中,导致很难建立树形关系
-
操作6个不同的javaBean,表结构有所不同,如何递归处理
-
递归关系一般是由一个表中的id与pid的子父关系,通过递归循环本集合,以实现tree结构,一个pid只能代表一个含义,但现在6个表中都有可能出现pid=1的情况,但id=1代表的含义有可能是科、属、目或别的类型的id=1
解决方法:
-
如果想要通过循环遍历,未免代码量太多,且不便于读取,并且执行效率底下,但如果想通过递归实现Tree树,需要根据pid关联上级,直到不能再细分便是递归出口,但pid会因为6个表出现重复的id,导致无法识别是否是上级的pid
-
所以不可以将6个entity集合合并去递归,那么想要递归却有6个entity集合,如何区分何时应该递归,出口应该如何定制,答案其实很简单,就是当循环完一层后设当前层循环数据为空,下次递归进来便因非空判断执行下一层,直到递归到最后一层 “属”,不再递归开始return,便有了出口
-
如何保证每次都是上下两级id与pid相互映射?那么就是循环本层分支带着上层的id与本层的pid比较
遇到的问题:
- 结果集每次每层只有一个树,原因是在循环中Childs用的是add,一定要注意修改为addAll,并且返回树集合
- 前端点击问题:设想如果用户点击某一层,需要做响应操作,传输的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;
}