在我们学习工作当中,树的这种结构已经屡见不鲜了,用的场景也很多
比如今天我为大家带来的就是工作中经常可能遇到的组织部门树 权限树 菜单树的构造
直接上张部门组织树的数据库设计吧
组织部门表
id 主键
name 名称
pid 父id
level 层级
seq 在当前层级下的顺序
remark 备注
这些是通用的字段 pid level(我没用上哈)seq 这些是这类问题的通解 的关键字段
在代码中 我们将依靠这些字段来递归进行树的构造 最后再按特定格式返给前端
下满上核心代码:
private Comparator comparator = new Comparator() {
@Override
public int compare(SysDeptModel s1, SysDeptModel s2) {
return s2.getSeq() - s1.getSeq();
}
};
@GetMapping("/tree.json")
public ResponseEnvelope toTree() {
//查询所有的组织结构
List treeModels = sysDeptService.selectPage(new SysDeptModel(), null);
Iterator iterator = treeModels.iterator();
//找出顶级组织机构(这里我们定义 顶级的pid为0 )
ArrayList rootNodes = Lists.newArrayList();
while (iterator.hasNext()) {
SysDeptModel node = iterator.next();
if (node.getParentId() == 0) {
rootNodes.add(node);
iterator.remove();
}
}
//为当前的组织机构排序(根据seq值)
if (!rootNodes.isEmpty()) {
rootNodes.sort(comparator);
}
//每隔从顶级开始递归寻找他们的子节点
if (!treeModels.isEmpty() && !rootNodes.isEmpty()) {
rootNodes.forEach(rootNode -> constructTree(rootNode, treeModels));
}
//返回结果
return ResponseEnvelopFactory.success(rootNodes);
}
/**
* 构造树
*
* @param parentNode 父节点
* @param treeModels 剩余节点
*/
private void constructTree(SysDeptModel parentNode, List treeModels) {
Iterator iterator = treeModels.iterator();
//保存子节点
List childrens = new ArrayList<>();
while (iterator.hasNext()) {
SysDeptModel node = iterator.next();
//找出下一级的节点
if (parentNode.getId().equals(node.getParentId())) {
childrens.add(node);
iterator.remove();
}
}
//为当前节点排序
if (!childrens.isEmpty()) {
childrens.sort(comparator);
}
//设置当前子节点为当前父节点的子集
if (!CollectionUtils.isEmpty(childrens)) {
parentNode.setChild(childrens);
}
//递归进行上述步骤 当我们的子节点没有时就一个顶级组织的递归就结束了
//当treeModels 空时 我们所有的顶级节点都把递归执行完了 就结束了
if (!CollectionUtils.isEmpty(treeModels) && !childrens.isEmpty()) {
childrens.forEach(node -> constructTree(node, treeModels));
}
}
看看我们的结果吧最后:
{
data: [
{
id: 2,
name: "总公司2",
seq: 1,
remark: "",
parentId: 0,
level: "0",
operator: "",
operteTime: 1536847342000,
operateIp: "",
child: [
{
id: 5,
name: "科技分公司",
seq: 1,
remark: "",
parentId: 2,
level: "1",
operator: "",
operteTime: 1536847351000,
operateIp: "",
child: [
{
id: 6,
name: "反特赛科技",
seq: 5,
remark: "",
parentId: 5,
level: "3",
operator: "",
operteTime: 1536847355000,
operateIp: "",
child: null
}
]
}
]
},
{
id: 1,
name: "总公司1",
seq: 0,
remark: "",
parentId: 0,
level: "0",
operator: "",
operteTime: 1536847338000,
operateIp: "",
child: [
{
id: 7,
name: "上海分公司",
seq: 5,
remark: "",
parentId: 1,
level: "2",
operator: "",
operteTime: 1536847473000,
operateIp: "",
child: null
},
{
id: 4,
name: "北京分公司",
seq: 3,
remark: "",
parentId: 1,
level: "1",
operator: "",
operteTime: 1538316148000,
operateIp: "",
child: null
},
{
id: 3,
name: "成都分公司",
seq: 2,
remark: "",
parentId: 1,
level: "1",
operator: "",
operteTime: 1536847345000,
operateIp: "",
child: null
}
]
}
],
status: true
}
结果是完全正确的哈 也有排序在的。
这就是这类问题的通用方法啦。