一个树型通用接口

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

  它们有共同的属性: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.

posted @ 2016-10-12 10:17  kstrive  阅读(3320)  评论(0编辑  收藏  举报