# Java树形结构拼接
场景,比如有菜单,一级菜单,二级菜单,三级菜单 子菜单pid等于父菜单id
@Data
class Menu {
private Integer id;
private Integer pid;
private String name;
private String url;
private Set<Menu> children = new HashSet<>();
public boolean isRoot() {
return this.pid == null || this.pid < 0;
}
}
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
方式一,双重for
private Set<Menu> menuTree1(Set<Menu> data) {
Set<Menu> res = new HashSet<>();
for (Menu menu : data) {
if (menu.isRoot()) {
res.add(menu);
}
for (Menu item : data) {
if (menu.getId().equals(item.getPid())) {
menu.getChildren().add(item);
}
}
}
return res;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
方式二,Map实现
private Set<Menu> menuTree2(Set<Menu> data) {
Set<Menu> rootSet = data.stream().filter(Menu::isRoot).collect(Collectors.toSet());
Map<Integer, Menu> menuMap = data.stream().collect(Collectors.toMap(Menu::getId, Function.identity()));
for (Menu item : data) {
if (menuMap.containsKey(item.getPid())) {
Menu Menu = menuMap.get(item.getPid());
Menu.getChildren().add(item);
}
}
return rootSet;
}
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
方式三,hutool工具类
private Set<Menu> menuTree2(Set<Menu> data) {
TreeNodeConfig config = new TreeNodeConfig(); // 配置
config.setIdKey("id"); // 树形数据中id的属性名
config.setDeep(3); // 展示目录深度,数据中一共四级目录
//转换器 1. null 这里表示根节点id (node, tree) node是原来的数据List中的item,tree是要返回的,可以任意定义字段
List<Tree<String>> list = TreeUtil.build(new ArrayList<>(data), null, config, (node, tree) -> {
tree.setId(node.getId().toString());
tree.setName(node.getName());
tree.setParentId(node.getPid() == null ? null : node.getPid().toString());
//其他节点
tree.put("url", node.getUrl());
});
//这个是为了展示而已,序列化为对象
List<Menu> resList = JSONUtil.toList(JSONUtil.toJsonStr(list), Menu.class);
return new HashSet<>(resList);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
测试数据
Set<Menu> getData() {
String s = "[{\"id\":101,\"name\":\"系统管理\",\"url\":\"/sys\",\"status\":1,\"createTime\":1652624114000,\"childPermissions\":[]},{\"id\":102,\"name\":\"商品管理\",\"url\":\"/goods\",\"status\":1,\"createTime\":1652624114000,\"childPermissions\":[]},{\"id\":103,\"name\":\"新闻管理\",\"url\":\"/news\",\"status\":1,\"createTime\":1652624114000,\"childPermissions\":[]},{\"id\":2001,\"pid\":101,\"name\":\"用户管理\",\"url\":\"/sys/users\",\"status\":1,\"createTime\":1652624114000,\"childPermissions\":[]},{\"id\":2002,\"pid\":101,\"name\":\"角色管理\",\"url\":\"/sys/roles\",\"status\":1,\"createTime\":1652624114000,\"childPermissions\":[]},{\"id\":2003,\"pid\":101,\"name\":\"权限管理\",\"url\":\"/sys/permission\",\"status\":1,\"createTime\":1652624114000,\"childPermissions\":[]},{\"id\":2004,\"pid\":102,\"name\":\"商品列表\",\"url\":\"/goods/goods\",\"status\":1,\"createTime\":1652624114000,\"childPermissions\":[]},{\"id\":2005,\"pid\":102,\"name\":\"分类列表\",\"url\":\"/goods/categorys\",\"status\":1,\"createTime\":1652624114000,\"childPermissions\":[]},{\"id\":2006,\"pid\":102,\"name\":\"订单列表\",\"url\":\"/goods/orders\",\"status\":1,\"createTime\":1652624114000,\"childPermissions\":[]},{\"id\":2007,\"pid\":103,\"name\":\"新闻列表\",\"url\":\"/news/news\",\"status\":1,\"createTime\":1652624114000,\"childPermissions\":[]},{\"id\":30001,\"pid\":2007,\"name\":\"新闻详情\",\"url\":\"/news/news/detail\",\"status\":1,\"createTime\":1652624114000,\"childPermissions\":[]}]";
Set<Menu> permissionList = new HashSet<>(JSONUtil.toList(s, Menu.class));
return permissionList;
}
@Test
void tree() {
Set<Menu> data = getData();
// 组装树形结构
Set<Menu> res = menuTree2(data);
System.out.println(JSONUtil.toJsonStr(res));
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
还有一个递归,这里没去测试