在实际业务场景中,经常遇到要将有父子关系的数据库表转成Java对象,这里就以集团公司的行政结构为例,采用递归算法算法解决这个场景的问题。
数据准备
为了简单起见,就不搞数据库了,直接用List模拟表中的数据。如下:
list.add(new TreeNode(0, null, "大集团"));
list.add(new TreeNode(1, 0, "科技公司"));
list.add(new TreeNode(2, 0, "文化传媒公司"));
list.add(new TreeNode(3, 0, "武昌办事处"));
list.add(new TreeNode(4, 0, "汉口办事处"));
list.add(new TreeNode(5, 1, "研发中心"));
list.add(new TreeNode(6, 1, "行政部"));
list.add(new TreeNode(7, 5, "技术部"));
list.add(new TreeNode(8, 5, "产品部"));
list.add(new TreeNode(9, 5, "运维部"));
list.add(new TreeNode(10, 2, "创作部"));
list.add(new TreeNode(11, 2, "行政部"));
实现逻辑
TreeNode
TreeNode类,表示数据节点
@Getter
@Setter
public class TreeNode {
private Integer id;
// 父节点ID,null表示这是根节点
private Integer parentId;
private String name;
// 叶子节点
private List<TreeNode> childNodes;
public TreeNode(Integer id, Integer parentId, String name) {
this.id = id;
this.parentId = parentId;
this.name = name;
this.childNodes = new ArrayList<>();
}
}
TreeNodeUtils
主要实现逻辑就是generateTree(int d) 方法,生成以id为根节点的树,递归为子节点以及子节点的子节点生成对应的树
public TreeNode generateTree(int id) {
TreeNode root = getById(id);
List<TreeNode> childNodes = getChildrenById(id);
if (childNodes != null && childNodes.size() > 0) {
for (TreeNode node : childNodes) {
// 将子节点作为根,查找子节点的子节点
TreeNode childRoot = generateTree(node.getId());
root.getChildNodes().add(childRoot);
}
}
return root;
}
根据id查找节点
private TreeNode getById(int id) {
for (TreeNode node : treeNodeList) {
if (node.getId() == id) {
return node;
}
}
return null;
}
查找id节点的所有子节点
private List getChildrenById(int id) {
List<TreeNode> childNodes = new ArrayList<>();
for (TreeNode node : treeNodeList) {
if (node.getParentId() != null && node.getParentId() == id) {
childNodes.add(node);
}
}
return childNodes;
}
TreeNodeUtils完整代码如下:
public class TreeNodeUtils {
private List<TreeNode> treeNodeList;
public TreeNodeUtils(List<TreeNode> treeNodeList) {
this.treeNodeList = treeNodeList;
}
/**
* 生成以id为根节点的树
*
* @param id
* @return
*/
public TreeNode generateTree(int id) {
TreeNode root = getById(id);
List<TreeNode> childNodes = getChildrenById(id);
if (childNodes != null && childNodes.size() > 0) {
for (TreeNode node : childNodes) {
// 将子节点作为根,查找子节点的子节点
TreeNode childRoot = generateTree(node.getId());
root.getChildNodes().add(childRoot);
}
}
return root;
}
/**
* 根据id查找节点
*
* @param id
* @return
*/
private TreeNode getById(int id) {
for (TreeNode node : treeNodeList) {
if (node.getId() == id) {
return node;
}
}
return null;
}
/**
* 根据id查找所有的子节点
*
* @param id
* @return
*/
private List getChildrenById(int id) {
List<TreeNode> childNodes = new ArrayList<>();
for (TreeNode node : treeNodeList) {
if (node.getParentId() != null && node.getParentId() == id) {
childNodes.add(node);
}
}
return childNodes;
}
}
测试
用前面准备的数据作为数据源来测试
public static void main(String[] args) {
List<TreeNode> data = initData();
TreeNodeUtils treeNodeUtils = new TreeNodeUtils(data);
TreeNode root = treeNodeUtils.generateTree(0);
System.out.println(JSON.toJSONString(root));
}
最后再看下执行结果
{
"childNodes":[
{
"childNodes":[
{
"childNodes":[
{
"childNodes":[],
"id":7,
"name":"技术部",
"parentId":5
},
{
"childNodes":[],
"id":8,
"name":"产品部",
"parentId":5
},
{
"childNodes":[],
"id":9,
"name":"运维部",
"parentId":5
}
],
"id":5,
"name":"研发中心",
"parentId":1
},
{
"childNodes":[],
"id":6,
"name":"行政部",
"parentId":1
}
],
"id":1,
"name":"科技公司",
"parentId":0
},
{
"childNodes":[
{
"childNodes":[],
"id":10,
"name":"创作部",
"parentId":2
},
{
"childNodes":[],
"id":11,
"name":"行政部",
"parentId":2
}
],
"id":2,
"name":"文化传媒公司",
"parentId":0
},
{
"childNodes":[],
"id":3,
"name":"武昌办事处",
"parentId":0
},
{
"childNodes":[],
"id":4,
"name":"汉口办事处",
"parentId":0
}
],
"id":0,
"name":"大集团"
}