一个树型通用接口

时间:2022-04-18 22:32:41

  项目中难免遇到使用树型结构,如部门、菜单等。

  它们有共同的属性:id,name,parentId,因此抽象出一个接口,然后使用一个工具类实现列表转树的功能。

  (其它这个是在另一个项目找到的,非原创,在此共享一下)

  看源码:

  1、树型结构接口TreeObject.java

import java.util.List;

/**
* 这个是列表树形式显示的接口
*/
public interface TreeObject {

Object getId();

void setId(Object id);

Object getParentId();

void setParentId(Object parentId);

String getName();

void setName(String name);

List getChildren();

void setChildren(List children);

}

  2、树型处理工具类TreeUtil.java

import org.apache.commons.lang3.StringUtils;

import java.util.*;

/**
* 把一个list集合,里面的bean含有 parentId 转为树形式
*
*/
public class TreeUtil {

/**
* 判断两个父ID是否相同
*
@param p1
*
@param p2
*
@return
*/
private boolean isEqualsParentId(Object p1,Object p2){
if(p1!=null && p1!=null){
return p1.equals(p2);
}
else if(p1==null && p2 == null) {
return true;
}
else if(p1==null && p2 != null) {
if("".equals(p2.toString())){
return true;
}
else{
return false;
}
}
else if(p1!=null && p2 == null) {
if("".equals(p1.toString())){
return true;
}
else{
return false;
}
}
else{
return false;
}
}

/**
* 根据父节点的ID获取所有子节点,该方法*节点必须为空
*
@param list 分类表
*
@param parentId 传入的父节点ID
*
@return String
*/
public List getChildTreeObjects(List<TreeObject> list,Object parentId) {
List returnList
= new ArrayList();
if(list!=null&&list.size()>0) {
for (Iterator<TreeObject> iterator = list.iterator(); iterator.hasNext(); ) {
TreeObject t
= (TreeObject) iterator.next();
// 一、根据传入的某个父节点ID,遍历该父节点的所有子节点
if (isEqualsParentId(t.getParentId(), parentId)) {
recursionFn(list, t);
returnList.add(t);
}
}
}
return returnList;
}

/**
* 根据父节点的ID获取所有子节点,该方法*节点可以不为空,非树直接返回
*
@param list 分类表
*
@return String
*/
public List<TreeObject> getChildTreeObjects(List<TreeObject> list) {
if(list!=null&&list.size()>0) {
List
<TreeObject> topList=new ArrayList<>();
List
<TreeObject> subList=new ArrayList<>();

Map
<String,String> idMap=new HashMap<>();

for (Iterator<TreeObject> iterator = list.iterator(); iterator.hasNext(); ) {
//归并所有list的id集合
TreeObject t = (TreeObject) iterator.next();
idMap.put(t.getId().toString(), t.getId().toString());
}

for (Iterator<TreeObject> iterator = list.iterator(); iterator.hasNext(); ) {
//获取最*的list
TreeObject t = (TreeObject) iterator.next();
if(t.getParentId()==null|| StringUtils.isEmpty(t.getParentId().toString())){
topList.add(t);
}
else{
String id
=idMap.get(t.getParentId().toString());
if(StringUtils.isEmpty(id)){
topList.add(t);
}
else{
subList.add(t);
}
}
}
if(topList!=null&&topList.size()>0&&subList!=null&&subList.size()>0){
List
<TreeObject> resultList=new ArrayList<>();
for (TreeObject t:topList) {
//将儿子级别的list归并到*中
List<TreeObject> subOneList=new ArrayList<>();

for (TreeObject sub:subList) {
// 一、根据传入的某个父节点ID,遍历该父节点的所有子节点
if (isEqualsParentId(sub.getParentId(), t.getId())) {
recursionFn(subList, sub);
subOneList.add(sub);
}
}
t.setChildren(subOneList);


resultList.add(t);
}
return resultList;
}
else{
return list;
}
}
return list;
}


/**
* 递归列表

*
@param list
*
@param t
*/
private void recursionFn(List<TreeObject> list, TreeObject t) {
List
<TreeObject> childList = getChildList(list, t);// 得到子节点列表
t.setChildren(childList);
for (TreeObject tChild : childList) {
if (hasChild(list, tChild)) {// 判断是否有子节点
//returnList.add(TreeObject);
Iterator<TreeObject> it = childList.iterator();
while (it.hasNext()) {
TreeObject n
= (TreeObject) it.next();
recursionFn(list, n);
}
}
}
}

// 得到子节点列表
private List<TreeObject> getChildList(List<TreeObject> list, TreeObject t) {

List
<TreeObject> tlist = new ArrayList<TreeObject>();
Iterator
<TreeObject> it = list.iterator();
while (it.hasNext()) {
TreeObject n
= (TreeObject) it.next();
if (isEqualsParentId(n.getParentId(),t.getId())) {
tlist.add(n);
}
}
return tlist;
}
List
<TreeObject> returnList = new ArrayList<TreeObject>();
/**
* 根据父节点的ID获取所有子节点
*
@param list 分类表
*
@param parentId 传入的父节点ID
*
@param prefix 子节点前缀
*/
public List<TreeObject> getChildTreeObjects(List<TreeObject> list, Object parentId,String prefix){
if(list == null) return null;
for (Iterator<TreeObject> iterator = list.iterator(); iterator.hasNext();) {
TreeObject node
= (TreeObject) iterator.next();
// 一、根据传入的某个父节点ID,遍历该父节点的所有子节点
if (isEqualsParentId(node.getParentId(),parentId)) {
recursionFn(list, node,prefix);
}
// 二、遍历所有的父节点下的所有子节点
/*if (node.getParentId()==0) {
recursionFn(list, node);
}
*/
}
return returnList;
}

private void recursionFn(List<TreeObject> list, TreeObject node,String p) {
List
<TreeObject> childList = getChildList(list, node);// 得到子节点列表
if (hasChild(list, node)) {// 判断是否有子节点
returnList.add(node);
Iterator
<TreeObject> it = childList.iterator();
while (it.hasNext()) {
TreeObject n
= (TreeObject) it.next();
n.setName(p
+n.getName());
recursionFn(list, n,p
+p);
}
}
else {
returnList.add(node);
}
}

// 判断是否有子节点
private boolean hasChild(List<TreeObject> list, TreeObject t) {
return getChildList(list, t).size() > 0 ? true : false;
}

}

  3、使用示例

  以菜单为例,菜单对象实现TreeObject接口

  (@ApiModel、@ApiModelProperty不需要的,是用于生成API文档的

import com.mjwon.core.tree.TreeObject;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;

import java.io.Serializable;
import java.util.List;

@ApiModel(value
= "菜单树对象")
public class MenuTreeDto implements Serializable, TreeObject {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value
= "菜单ID", example = "1", required = true)
private String id;
@ApiModelProperty(value
= "菜单名称", example = "菜单", required = true)
private String menuName;
@ApiModelProperty(value
= "菜单类型", example = "1", required = true)
private Short menuType;
@ApiModelProperty(value
= "菜单代码", example = "1", required = true)
private String menuCode;
@ApiModelProperty(value
= "父节点ID", example = "2", required = true)
private String parentId;
@ApiModelProperty(value
= "排序", example = "2", required = false)
private Long sortNo;
@ApiModelProperty(value
= "展开状态", example = "1/0", required = true)
private Short expand;
@ApiModelProperty(value
= "是否为叶子", example = "0/1", required = true)
private Short isShow;
@ApiModelProperty(value
= "权限标识", example = "task.scheduled", required = true)
private String permission;
@ApiModelProperty(value
= "备注", example = "备注", required = false)
private String comt;
@ApiModelProperty(value
= "是否启用", example = "1/0", required = false)
private Short enable;
@ApiModelProperty(value
= "节点图标CSS类名", example = "fa fas", required = false)
private String iconcls;
@ApiModelProperty(value
= "请求地址", example = "app.syslog", required = false)
private String request;
@ApiModelProperty(value
= "子部门", example = "父节点", required = false)
private List children;

@Override
public Object getId() {
return this.id;
}

@Override
public void setId(Object id) {
this.id = (String) id;
}

@Override
public Object getParentId() {
return this.parentId;
}

@Override
public void setParentId(Object parentId) {
this.parentId = (String) parentId;
}

@Override
public String getName() {
return this.menuName;
}

@Override
public void setName(String name) {
this.menuName = name;
}

@Override
public List getChildren() {
return this.children;
}

@Override
public void setChildren(List children) {
this.children = children;
}

public void setId(String id) {
this.id = id;
}

public String getMenuName() {
return menuName;
}

public void setMenuName(String menuName) {
this.menuName = menuName;
}

public Short getMenuType() {
return menuType;
}

public void setMenuType(Short menuType) {
this.menuType = menuType;
}

public void setParentId(String parentId) {
this.parentId = parentId;
}

public Long getSortNo() {
return sortNo;
}

public void setSortNo(Long sortNo) {
this.sortNo = sortNo;
}

public Short getExpand() {
return expand;
}

public void setExpand(Short expand) {
this.expand = expand;
}

public Short getIsShow() {
return isShow;
}

public void setIsShow(Short isShow) {
this.isShow = isShow;
}

public String getPermission() {
return permission;
}

public void setPermission(String permission) {
this.permission = permission;
}

public String getComt() {
return comt;
}

public void setComt(String comt) {
this.comt = comt;
}

public Short getEnable() {
return enable;
}

public void setEnable(Short enable) {
this.enable = enable;
}

public String getIconcls() {
return iconcls;
}

public void setIconcls(String iconcls) {
this.iconcls = iconcls;
}

public String getRequest() {
return request;
}

public void setRequest(String request) {
this.request = request;
}

public String getMenuCode() {
return menuCode;
}

public void setMenuCode(String menuCode) {
this.menuCode = menuCode;
}
}

  查询出菜单对的所有数据,然后转为树结构即可 

     List dtoList = BeanMapper.mapList(menuList,MenuTreeDto.class);
if(dtoList!=null && dtoList.size()>0) {
TreeUtil treeUtil
= new TreeUtil();
List
<MenuTreeDto> treeList = treeUtil.getChildTreeObjects(dtoList, parentId);
return treeList;
}

 

    生成树的结构示例:菜单树JSON

一个树型通用接口一个树型通用接口
{
"success": true,
"message": "请求成功",
"data": [
{
"id": "1",
"menuName": "系统管理",
"menuType": 1,
"menuCode": "sys",
"parentId": "0",
"sortNo": 50,
"expand": 0,
"isShow": 1,
"permission": "sys",
"comt": "test",
"enable": 1,
"iconcls": "fa fa-angle-right",
"request": "#",
"children": [
{
"id": "16",
"menuName": "用户角色",
"menuType": 1,
"menuCode": "user.role",
"parentId": "1",
"sortNo": 11,
"expand": 0,
"isShow": 0,
"permission": "user.role",
"comt": null,
"enable": 1,
"iconcls": "fa fa-users",
"request": "app.sys.userroles",
"children": null,
"name": "用户角色"
},
{
"id": "17",
"menuName": "权限管理",
"menuType": 1,
"menuCode": "sys.access",
"parentId": "1",
"sortNo": 12,
"expand": 0,
"isShow": 1,
"permission": "sys.access",
"comt": null,
"enable": 1,
"iconcls": "fa fa-list",
"request": "app.sys.auth",
"children": null,
"name": "权限管理"
},
{
"id": "18",
"menuName": "系统日志",
"menuType": 1,
"menuCode": "sys.syslog",
"parentId": "1",
"sortNo": 22,
"expand": 1,
"isShow": 1,
"permission": "sys.syslog",
"comt": null,
"enable": 1,
"iconcls": "fa fa-list",
"request": "app.syslog",
"children": null,
"name": "系统日志"
},
{
"id": "19",
"menuName": "业务日志",
"menuType": 1,
"menuCode": "sys.log.business",
"parentId": "1",
"sortNo": 999,
"expand": 1,
"isShow": 1,
"permission": "sys.log.business",
"comt": null,
"enable": 1,
"iconcls": "fa fa-list",
"request": "app.businesslog",
"children": null,
"name": "业务日志"
},
{
"id": "2",
"menuName": "用户管理",
"menuType": 1,
"menuCode": "sys.user",
"parentId": "1",
"sortNo": 1,
"expand": 0,
"isShow": 1,
"permission": "sys.user",
"comt": null,
"enable": 1,
"iconcls": "fa fa-user",
"request": "app.user",
"children": null,
"name": "用户管理"
},
{
"id": "3",
"menuName": "部门管理",
"menuType": 1,
"menuCode": "sys.dept",
"parentId": "1",
"sortNo": 2,
"expand": 0,
"isShow": 1,
"permission": "sys.dept",
"comt": null,
"enable": 1,
"iconcls": "fa fa-users",
"request": "app.dept",
"children": null,
"name": "部门管理"
},
{
"id": "4",
"menuName": "菜单管理",
"menuType": 1,
"menuCode": "sys.menu",
"parentId": "1",
"sortNo": 3,
"expand": 0,
"isShow": 1,
"permission": "sys.menu",
"comt": null,
"enable": 1,
"iconcls": "fa fa-bars",
"request": "app.menu",
"children": null,
"name": "菜单管理"
},
{
"id": "5",
"menuName": "角色管理",
"menuType": 1,
"menuCode": "sys.role",
"parentId": "1",
"sortNo": 4,
"expand": 0,
"isShow": 1,
"permission": "sys.role",
"comt": null,
"enable": 1,
"iconcls": "fa fa-cog",
"request": "app.role",
"children": null,
"name": "角色管理"
},
{
"id": "6",
"menuName": "会话管理",
"menuType": 1,
"menuCode": "sys.session",
"parentId": "1",
"sortNo": 6,
"expand": 0,
"isShow": 0,
"permission": "sys.session",
"comt": null,
"enable": 1,
"iconcls": "fa fa-list",
"request": "main.sys.session.list",
"children": null,
"name": "会话管理"
},
{
"id": "7",
"menuName": "字典管理",
"menuType": 1,
"menuCode": "sys.dic",
"parentId": "1",
"sortNo": 7,
"expand": 0,
"isShow": 1,
"permission": "sys.dic",
"comt": null,
"enable": 1,
"iconcls": "fa fa-book",
"request": "app.dictindex",
"children": null,
"name": "字典管理"
},
{
"id": "8",
"menuName": "业务参数",
"menuType": 1,
"menuCode": "sys.param",
"parentId": "1",
"sortNo": 8,
"expand": 0,
"isShow": 0,
"permission": "sys.param",
"comt": null,
"enable": 1,
"iconcls": "fa fa-wrench",
"request": "main.sys.param.list",
"children": null,
"name": "业务参数"
},
{
"id": "20",
"menuName": "数据权限",
"menuType": 1,
"menuCode": "sys.dataauth",
"parentId": "1",
"sortNo": 20,
"expand": 1,
"isShow": 1,
"permission": "sys.dataauth",
"comt": null,
"enable": 1,
"iconcls": "fa fa-users",
"request": "app.dataauth",
"children": null,
"name": "数据权限"
}
],
"name": "系统管理"
},
{
"id": "9",
"menuName": "调度中心",
"menuType": 1,
"menuCode": "task",
"parentId": "0",
"sortNo": 2,
"expand": 0,
"isShow": 0,
"permission": "task",
"comt": null,
"enable": 1,
"iconcls": "fa fa-angle-right",
"request": "#",
"children": [
{
"id": "10",
"menuName": "任务组管理",
"menuType": 1,
"menuCode": "task.group",
"parentId": "9",
"sortNo": 1,
"expand": 0,
"isShow": 0,
"permission": "task.group",
"comt": null,
"enable": 1,
"iconcls": "fa fa-tasks",
"request": "main.task.group.list",
"children": null,
"name": "任务组管理"
},
{
"id": "11",
"menuName": "任务管理",
"menuType": 1,
"menuCode": "task.scheduler",
"parentId": "9",
"sortNo": 2,
"expand": 0,
"isShow": 0,
"permission": "task.scheduler",
"comt": null,
"enable": 1,
"iconcls": "fa fa-table",
"request": "main.task.scheduler.list",
"children": null,
"name": "任务管理"
},
{
"id": "12",
"menuName": "调度管理",
"menuType": 1,
"menuCode": "task.scheduled",
"parentId": "9",
"sortNo": 3,
"expand": 0,
"isShow": 0,
"permission": "task.scheduled",
"comt": null,
"enable": 1,
"iconcls": "fa fa-user",
"request": "main.task.scheduled.list",
"children": null,
"name": "调度管理"
},
{
"id": "13",
"menuName": "调度日志",
"menuType": 1,
"menuCode": "task.log",
"parentId": "9",
"sortNo": 4,
"expand": 0,
"isShow": 0,
"permission": "task.log",
"comt": null,
"enable": 1,
"iconcls": "fa fa-list",
"request": "main.task.log.list",
"children": null,
"name": "调度日志"
},
{
"id": "15",
"menuName": "角色权限",
"menuType": 1,
"menuCode": "role.access",
"parentId": "9",
"sortNo": 11,
"expand": 1,
"isShow": 1,
"permission": "role.access",
"comt": null,
"enable": 1,
"iconcls": "fa fa-list",
"request": "app.sys.roleaccess",
"children": null,
"name": "角色权限"
}
],
"name": "调度中心"
}
]
}
View Code

   至此,可以方便实现树结构JSON的返回。over.