java 利用递归,list,map实现树形结构,根据节点找到父节点,根据节点找到子节点
实现目录
前言
以下代码说明:实现的数据都只是基于以下## 2.数据库结构
一、部门树的实现方法一(Map)
1.部门树结构
{
"id": 1,
"orgCode": "000012",
"parentCode": null,
"orgName": "xxxx省监督管理局",
"children": [
{
"id": 2,
"orgCode": "00001201",
"parentCode": "000012",
"orgName": "xxx区管理局",
"children": [
{
"id": 5,
"orgCode": "000012011",
"parentCode": "00001201",
"orgName": "xxx村管理局",
"children":""
}
}
]
}
2.数据库结构
3.vo对象:
@Data
public class OrganizationVo {
/**
* 部门id
*/
private Integer id;
/**
* 部门编码
*/
private String orgCode;
/**
* 部门父编码
*/
private String parentCode;
/**
* 部门名称
*/
private String orgName;
/**
* 子部门列表 这里用list类型也是一样的
*/
@JsonInclude(JsonInclude.Include.NON_NULL)
private Collection<OrganizationVo> children;
}
4.代码实现
public List<OrganizationVo> getOrgAll(){
//获取所有部门
List<OrganizationVo> organizationVos = xxxx方法.listAll();
List<OrganizationVo> list = new ArrayList<>();
Map<String , OrganizationVo> map = new HashMap<>();
//把所有部门转化成map结构,key为组织编码,value为组织对象
for (OrganizationVo organizationVo : organizationVos) {
if (StringUtils.isNotBlank(organizationVo.getParentCode())){
map.put(organizationVo.getOrgCode(), organizationVo);
}
}
//实现树形结构
for (OrganizationVo organizationVo : organizationVos) {
String code = organizationVo.getParentCode();
OrganizationVo parent = map.get(code);
//根据最高级组织中parentCode为空或者以parentCode为组织编码查不到组织的原理,把最高级组织对象add到list结构中
if (ObjectUtils.isEmpty(parent)){
list.add(organizationVo);
}else {
Collection<OrganizationVo> children = parent.getChildren();
if (CollectionUtils.isEmpty(children)){
parent.setChildren(new ArrayList<>());
}
parent.getChildren().add(organizationVo);
}
}
return list;
}
二、部门树的实现方法二(MyBatis)
虽然可以实现但是查询速度很慢 效率低 在多数据时不推荐使用
1.方法
List<OrganizationVo> listAll();
2.mybatis实现
<resultMap id="ResourceResultMap" type="xxxx.xxxx.OrganizationVo">
<collection property="children" column="{orgParentCode=orgCode}" select="getChildrenTree"/>
</resultMap>
<select id="listAll" resultMap="ResourceResultMap">
select id, org_code orgCode, org_parent_code parentCode, org_name orgName, creator
from sys_organization
</select>
<select id="getChildrenTree" resultType="xxxx.xxxx.OrganizationVo">
select *
from sys_organization where org_parent_code=#{orgParentCode}
</select>
三、通过orgCode(节点编码)返回包含此orgCode在内的所有子orgCode列表(可以实现获取该orgCode下(包括子集)所有对应的用户)
1.使用递归实现
代码实现:
string orgCode="00001201"
ArrayList<String> list = new ArrayList<>();
//查询所有组织
List<OrganizationVo> all = xxxxx方法.listAll();
//递归
List<String> codeList = getChildrenCode(orgCode, all, list);
codeList.add(orgCode);
System.out.println(codeList); //["000012011","00001201"]
2.递归方法
代码如下:
public List<String> getChildrenCode(String orgCode, List<OrganizationVo> all, List<String> list) {
for (OrganizationVo d : all) {
if (orgCode.equals(d.getParentCode())) {
list.add(d.getOrgCode());
getChildrenCode(d.getOrgCode(), all, list);
}
}
return list;
}
四、通过orgCode返回所有父级code
1.方法
/**
* 根据部门id查询部门父级
* @param orgCode
* @param sysOrganizations
* @return
*/
public void completeOrg() {
String orgCode="000012011"
//查询所有组织
List<OrganizationVo> sysOrganizations = xxxxx方法.listAll();
// key是 资源id, value 是 父id
Map<String, String> collect = sysOrganizations
.stream()
.collect(
Collectors.toMap(
SysOrganization::getOrgCode,
it -> (it.getOrgParentCode() == null) ? it.getOrgCode() : it.getOrgParentCode(),
(v1, v2) -> v2
)
);
Set<String> resSet = new HashSet<>();
orgFindParent(resSet, collect, orgCode);
String a[]=resSet.stream()
.map(String::valueOf).sorted()
.toArray(String[]::new);
System.out.println(a);//["000012","00001201","000012011"]
}
2.递归方法
/**
* 部门: 路径压缩,查询父节点
* @param
*/
private static void orgFindParent(Set<String> orgSet, Map<String,String > orgMap , String orgCode) {
if (StringUtils.isNotBlank(orgCode)){
while (!orgCode.equals(orgMap.get(orgCode))) {
//亲身教训:如果不加一下判断的话,如果orgMap.get(orgCode))为空时(当部门有父级code,但是父级部门又不存在数据库时),会进入死循环
if (StringUtils.isNotBlank(orgMap.get(orgCode))){
orgSet.add(orgCode);
String parent = orgMap.get(orgCode);
if (StringUtils.isNotBlank(parent)) {
orgMap.put(orgCode, orgMap.get(parent));
orgCode = parent;
}
orgSet.add(orgCode);
}else {
//若orgCode为空时则移除,(当父级parentCode存在,但是却没有父级部门信息时,应移除父级code)
orgSet.remove(orgCode);
break;
}
}
}
}
五、根据部门编码,获取二级code
1.方法
String a="000012011";
String secondOrgCode=null;
SysOrganization organization=new SysOrganization();
secondOrgCode= secondOrganization(a,secondOrgCode,organization);
System.out.println("secondOrgCode = " + secondOrgCode); //00001201
2.递归方法
private String secondOrganization(String orgCode,String secondOrgCode,SysOrganization organization) {
secondOrgCode=organization.getOrgCode();
organization= organizationService.getByOrgCode(orgCode);
if (!ObjectUtils.isEmpty(organization.getId()) ){
if (organizationService.getByOrgCode(organization.getOrgParentCode()).getId()!=null&&StringUtils.isNotBlank(organization.getOrgParentCode())){
return this.secondOrganization(organization.getOrgParentCode(),secondOrgCode,organization);
}
}
return secondOrgCode;
}