JAVA树状结构返回方式-列表拼装树状结构,不要整天说不会拼装数据了
第一种:自己写个递归拼装
//定义一个树状结构的类
@Data
static class Column{
private Integer id;
private String name;
private Integer parentId;
private List<Column> children;
}
public static void main(String[] args) {
Column column1 = new Column();
column1.setId(1);
column1.setName("一号栏目");
column1.setParentId(0);//一级栏目设置为0
Column column2 = new Column();
column2.setId(2);
column2.setName("二号栏目");
column2.setParentId(0);//一级栏目设置为0
Column column3 = new Column();
column3.setId(3);
column3.setName("一号栏目的大儿子");
column3.setParentId(1);//父ID设置为1级栏目
Column column4 = new Column();
column4.setId(4);
column4.setName("一号栏目的二儿子");
column4.setParentId(1);//父ID设置为一号栏目
Column column5 = new Column();
column5.setId(5);
column5.setName("二号栏目的大儿子");
column5.setParentId(2);//父ID设置为二号栏目
Column column6 = new Column();
column6.setId(6);
column6.setName("一号栏目的孙子");
column6.setParentId(4);//父ID设置为一号栏目的二儿子
List<Column> columns = new ArrayList<>();
columns.add(column1);
columns.add(column2);
columns.add(column3);
columns.add(column4);
columns.add(column5);
columns.add(column6);
//我的一级节点是0,此处就传0
List<Column> columnTree = getColumnTree(columns, 0);
System.out.println(columnTree);
}
/**
* 递归拼装
* @param sourseColumn
* @param id 父节点ID
* @return
*/
private static List<Column> getColumnTree(List<Column> sourseColumn,Integer id){
List<Column> resultColumn = new ArrayList<>();
List<Column> newColumns = new CopyOnWriteArrayList<>(sourseColumn);
Safes.of(newColumns).forEach(column -> {
if(column.getParentId().equals(id)){
//只要存在过就删除掉,这样递归循环的时候能少循环很多遍
newColumns.remove(column);
column.setChildren(getColumnTree(newColumns,column.getId()));
resultColumn.add(column);
}
});
return resultColumn;
}
备注1:Safes.of() 方法是一个非空验证工具类,点这里查看Safes.of()
备注2:使用CopyOnWriteArrayList是为了方便在循环的时候删除数组中的元素,直接remove会空指针
第二种:使用hutool第三方类库(其实原理也是递归)
1.maven引入
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.6.7</version>
</dependency>
1.使用
//数据库里面查出来的数据列表,此处还用上文中建的假数据
List<Column> columns = new ArrayList<>();
//固定写法,定义一些属性
TreeNodeConfig treeNodeConfig = new TreeNodeConfig();
// 自定义属性名,默认拼装成功后返回的字段名是id,name,children等,可以自定义修改
// 也可以不配置,根据业务需要来
treeNodeConfig.setIdKey("columnId");//我想把返回的id改成给我返回columnId
treeNodeConfig.setNameKey("title");//我想把返回的name字段,改成title
treeNodeConfig.setChildrenKey("erZi");//我想把返回的children字段,改成erZi(儿子)
treeNodeConfig.setParentIdKey("fatherId");//我想把返回的parentId字段,改成fatherId
treeNodeConfig.setWeightKey("menuSort");//返回的对象权重改个名,不改名的话默认是weightKey
// 最大递归深度,我这里是两层结构,就写了个2
treeNodeConfig.setDeep(2);
//转换器,参数(列表,一级栏目的父ID,treeNodeConfig)
List<Tree<String>> treeNodes = TreeUtil.build(columns, "0", treeNodeConfig,
(treeNode, tree) -> {
// 固定参数 ,我的示例参数里没有排序字段,就用了ID排序
tree.setId(treeNode.getId().toString());
tree.setParentId(treeNode.getParentId().toString());
tree.setWeight(treeNode.getId());
tree.setName(treeNode.getName());
// 扩展属性 ... (根据业务需要来,需要啥就返回啥,不需要后面就不写)
tree.putExtra("suiBian1", treeNode.getName());
tree.putExtra("suiBian2", treeNode.getName());
tree.putExtra("suiBian3", treeNode.getName());
tree.putExtra("xiaXie1", treeNode.getName());
tree.putExtra("xiaXie2", treeNode.getName());
tree.putExtra("xiaXie3", treeNode.getName());
});
两种方式效率问题
差不多,可以忽略不计
码字不易,我自己手写的,非复制,如果对你有些许帮助,点个赞再走吧。