一个复杂业务树的构造工具类

因公司业务需求,需要构造各种类型组织关系树。
有同种模型的关系树,例如 单位、子单位关系树
也有不同模型的关系树,例如 单位、子单位、部门、子部门关系树

那么基于这种复杂的关系树,我们需要将树的基本结构关系以及业务代码做分离

源码地址
https://github.com/zhaojun123/tree.git

首先构造一个树的基类

/**
 * 树的抽象
 */
public abstract class Tree{

    private List<Tree> childrenList = new ArrayList<>();

    /**
     * 获取树节点id
     * @return
     */
    abstract Object getTreeId();

    /**
     * 获取树父节点id
     * @return
     */
    abstract Object getTreeParentId();

    /**
     * 该节点的子节点集合
     * @return
     */
    public List<Tree> getTreeChildrenList(){
        return childrenList;
    }

    /**
     * 判断是否是根节点,默认TreeParentId为null即为根节点,子类可以覆盖该逻辑
     * @return
     */
    protected boolean topParentId(){
        return getTreeParentId() == null;
    }
}

再模拟实际业务场景构建单位模型 和 部门模型,继承该基类

/**
 * 单位模型
 */
public class OrganTree extends Tree{

    public OrganTree(String organId,String parentOrganId,String organName){
        this.organId = organId;
        this.parentOrganId = parentOrganId;
        this.organName = organName;
    }

	/**
     * 这里需要将业务字段 和 树的关系字段绑定,确定id 和 parentId
     * @return
     */
    @Override
    public Object getTreeId() {
        return organId;
    }

    @Override
    public Object getTreeParentId() {
        return parentOrganId;
    }
	//省略了相应的get set 方法
}

//部门模型
public class DeptTree extends Tree{

    public DeptTree(String deptId,String parentDeptId,String organId,String deptName){
        this.deptId = deptId;
        this.parentDeptId = parentDeptId;
        this.organId = organId;
        this.deptName = deptName;
    }

    private String deptId;

    private String parentDeptId;

    private String organId;

    private String deptName;

    /**
     * 这里需要将业务字段 和 树的关系字段绑定,确定id 和 parentId
     * @return
     */
    @Override
    public Object getTreeId() {
        return deptId;
    }

    @Override
    public Object getTreeParentId() {
        return parentDeptId;
    }
    //省略了相应的get set 方法
}

工具类TreeUtils,根据getTreeId、getTreeParentId构建Tree模型的关系

/**
 * 构建树的工具类
 */
public class TreeUtils {

    public static <T>List<T> tree(List<T> treeList){
        return tree(treeList,null);
    }

    /**
     * 在组装树的过程中,调用Consumer函数执行自定义的业务逻辑
     * @param treeList
     * @param afterAddChildren
     * @param <T>
     * @return
     */
    public static <T> List<T> tree(List<T> treeList, Consumer<Tree> afterAddChildren){
        List<T> resultList = new ArrayList();
        for(Object object: treeList){
            Tree tree = (Tree)object;
            if(tree.topParentId()){
                resultList.add((T)tree);
                treeRecursion(tree,(List<Tree>)treeList,afterAddChildren);
            }
        }
        return resultList;
    }

    /**
     * 递归方法组装树
     * @param nodeTree
     * @param treeList
     * @param afterAddChildren
     */
    private static void treeRecursion(Tree nodeTree,List<Tree> treeList,Consumer<Tree> afterAddChildren){
        for(Tree tree:treeList){
            if(nodeTree.getTreeId().equals(tree.getTreeParentId())){
                nodeTree.getTreeChildrenList().add(tree);
                treeRecursion(tree,treeList,afterAddChildren);
            }
        }
        if(afterAddChildren!=null)
            afterAddChildren.accept(nodeTree);
    }

}

测试类
构建几个上下级单位,以及内部的上下级部门,并将其关系用树表现出来

public class TreeTest {

    public static void main(String[] args) {
        TreeTest treeTest = new TreeTest();
        List<OrganTree> organList = treeTest.getOrganList();
        List<OrganTree> resultList = TreeUtils.tree(organList
                ,(tree -> {
                        //如果树节点是单位,则继续查下面的部门
                        if(tree instanceof OrganTree){
                            OrganTree organTree = (OrganTree)tree;
                            List<DeptTree> deptTreeList
                                    = treeTest.getDeptByOrgan(organTree.getOrganId());
                            //把部门加入单位的子节点中,继续构造部门树
                            tree.getTreeChildrenList().addAll(TreeUtils.tree(deptTreeList));
                        }
                    }
                )
        );
        System.out.println(new Gson().toJson(resultList));
    }

    /**
     * 模拟数据库查询获取所有公司的列表
     * @return
     */
    public List<OrganTree> getOrganList(){
        List<OrganTree> list = new ArrayList<>();
        list.add(new OrganTree("1",null,"中科美络"));
        list.add(new OrganTree("2",null,"移动互联"));
        list.add(new OrganTree("3","1","中科子公司1"));
        list.add(new OrganTree("4","1","中科子公司2"));
        return list;
    }

    /**
     * 模拟数据库查询 中科美络 和 子公司2下面的部门
     * @param organId
     * @return
     */
    public List<DeptTree> getDeptByOrgan(String organId){
        List<DeptTree> list = new ArrayList<>();
        if(organId.equals("4")){
            list.add(new DeptTree("1",null,"1","总经办"));
            list.add(new DeptTree("2","1","1","人事"));
            list.add(new DeptTree("3","1","1","财务"));
            list.add(new DeptTree("4","2","1","开发"));
        }
        if(organId.equals("1")){
            list.add(new DeptTree("1",null,"1","总经办"));
        }
        return list;
    }

}

打印

[{
	"organId": "1",
	"organName": "中科美络",
	"childrenList": [{
		"organId": "3",
		"parentOrganId": "1",
		"organName": "中科子公司1",
		"childrenList": []
	}, {
		"organId": "4",
		"parentOrganId": "1",
		"organName": "中科子公司2",
		"childrenList": [{
			"deptId": "1",
			"organId": "1",
			"deptName": "总经办",
			"childrenList": [{
				"deptId": "2",
				"parentDeptId": "1",
				"organId": "1",
				"deptName": "人事",
				"childrenList": [{
					"deptId": "4",
					"parentDeptId": "2",
					"organId": "1",
					"deptName": "开发",
					"childrenList": []
				}]
			}, {
				"deptId": "3",
				"parentDeptId": "1",
				"organId": "1",
				"deptName": "财务",
				"childrenList": []
			}]
		}]
	}, {
		"deptId": "1",
		"organId": "1",
		"deptName": "总经办",
		"childrenList": []
	}]
}, {
	"organId": "2",
	"organName": "移动互联",
	"childrenList": []
}]
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值