package com.example.designpattern;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSONArray;
import java.io.File;
import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class TreeConverter2 {
private static final String separator = ",";
/**
* 构建树形结构
*
* @param nodes
* @return
*/
public static List<TreeNode> buildTree(List<TreeNode> nodes) {
List<TreeNode> rootNodes = nodes.stream().filter(node -> node.getRoute().split(separator).length == 1).collect(Collectors.toList());
for (TreeNode rootNode : rootNodes) {
addChildTreeNodes(rootNode, nodes);
}
return rootNodes;
}
/**
* 添加树形节点
*
* @param parent
* @param nodes
*/
private static void addChildTreeNodes(TreeNode parent, List<TreeNode> nodes) {
String parentRoute = parent.getRoute();
List<TreeNode> childNodes = getChildrenTreeNode(parentRoute, nodes);
if (CollUtil.isNotEmpty(childNodes)) {
parent.setChildren(new ArrayList<>());
}
for (TreeNode childNode : childNodes) {
parent.getChildren().add(childNode);
addChildTreeNodes(childNode, nodes);
}
}
/**
* 获取当前节点下的元素
*
* @param level
* @param allNodeList
* @return
*/
private static List<TreeNode> getChildrenTreeNode(String level, List<TreeNode> allNodeList) {
String[] levelParts = level.split(separator);
List<TreeNode> list = new ArrayList<>();
for (TreeNode item : allNodeList) {
String[] routeParts = item.getRoute().split(separator);
if (routeParts.length == levelParts.length + 1 && isAllEqual(levelParts, routeParts, levelParts.length)) {
list.add(item);
}
}
return list;
}
/**
* 判断数组前n个元素是否相等
*
* @param array1
* @param array2
* @param n
* @return
*/
public static boolean isAllEqual(String[] array1, String[] array2, int n) {
if (array1 == null || array2 == null || n > Math.min(array1.length, array2.length)) {
return false;
}
for (int i = 0; i < n; i++) {
if (!StrUtil.equals(array1[i], array2[i])) {
return false;
}
}
return true;
}
/**
* 树形结构转列表
*
* @param rootList
* @return
*/
public List<TreeNode> treeToGridList(List<TreeNode> rootList) {
List<TreeNode> gridList = new ArrayList<>();
Map<String, String> routeMap = new HashMap<>();
for (int i = 0; i < rootList.size(); i++) {
TreeNode rootNode = rootList.get(i);
String currentRoute = String.valueOf(i + 1);
generateGridList(rootNode, 1, currentRoute, routeMap, gridList);
}
return gridList;
}
/**
* 生成列表
*
* @param node
* @param currentLevel
* @param currentRoute
* @param routeMap
* @param gridList
*/
private void generateGridList(TreeNode node, int currentLevel, String currentRoute, Map<String, String> routeMap, List<TreeNode> gridList) {
if (ObjectUtil.isEmpty(node)) {
return;
}
gridList.add(new TreeNode(node.getId(), node.getName(), currentRoute));
if (CollUtil.isNotEmpty(node.getChildren())) {
for (TreeNode child : node.getChildren()) {
int nextLevel = currentLevel + 1;
generateGridList(child, nextLevel, calculateNextRoute(nextLevel, currentRoute, routeMap), routeMap, gridList);
}
}
}
/**
* 计算下一个节点路径
*
* @param nextLevel
* @param currentRoute
* @param routeMap
* @return
*/
private String calculateNextRoute(int nextLevel, String currentRoute, Map<String, String> routeMap) {
String[] routeParts = StrUtil.split(currentRoute, separator);
String newRoute = ArrayUtil.join(ArrayUtil.append(routeParts, String.valueOf(nextLevel)), separator);
while (routeMap.containsKey(newRoute)) {
String[] finalRouteParts = routeParts;
List<String> matchingRoutes = routeMap.entrySet().stream()
.filter(entry -> entry.getKey().split(separator).length == finalRouteParts.length + 1
&& isAllEqual(entry.getKey().split(separator), finalRouteParts, finalRouteParts.length))
.map(Map.Entry::getKey)
.sorted().collect(Collectors.toList());
String lastRoute = matchingRoutes.get(matchingRoutes.size() - 1);
int maxLevel = Integer.parseInt(lastRoute.split(separator)[lastRoute.split(separator).length - 1]);
routeParts = ArrayUtil.append(routeParts, String.valueOf(maxLevel + 1));
newRoute = ArrayUtil.join(routeParts, separator);
}
routeMap.put(newRoute, newRoute);
return newRoute;
}
public static void main(String[] args) throws Exception {
String json = IoUtil.read(new FileInputStream(new File("F:\\project\\design-pattern\\src\\main\\resources\\test2.json")), "utf-8");
List<TreeNode> list = JSONArray.parseArray(json, TreeNode.class);
List<TreeNode> grid = new TreeConverter2().treeToGridList(list);
// 打印二维表
List<TreeNode> ss = new ArrayList<>();
for (TreeNode row : grid) {
System.out.println(row);
TreeNode treeNode = new TreeNode(row.getId(), row.getName(), row.getRoute());
ss.add(treeNode);
}
System.out.println("-------------------");
List<TreeNode> treeNodeList = buildTree(ss);
System.out.println(JSONArray.toJSONString(treeNodeList));
}
}
package com.example.designpattern;
import java.io.Serializable;
import java.util.List;
public class TreeNode implements Serializable {
private String id;
private String name;
private String route;
private List
public TreeNode(String id, String name, String route) {
this.id = id;
this.name = name;
this.route = route;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getRoute() {
return route;
}
public void setRoute(String route) {
this.route = route;
}
public List<TreeNode> getChildren() {
return children;
}
public void setChildren(List<TreeNode> children) {
this.children = children;
}
@Override
public String toString() {
return "TreeNode{" +
"id='" + id + '\'' +
", name='" + name + '\'' +
", route='" + route + '\'' +
'}';
}
}
[{
"children": [{
"children": [{
"children": [{
"children": [{
"children": [{
"id": "2-1---1",
"name": "叶子节点23111",
"route": "1,2,3,4,5,6"
}],
"id": "2-1---1",
"name": "叶子节点231111",
"route": "1,2,3,4,5"
}],
"id": "2-1--1",
"name": "叶子节点2321111",
"route": "1,2,3,4"
}],
"id": "1-1-1-1",
"name": "叶子节点221111",
"route": "1,2,3"
}, {
"id": "1-2-2",
"name": "叶子节点2222",
"route": "1,2,4"
}, {
"id": "1-3-3",
"name": "叶子节点2233",
"route": "1,2,5"
}, {
"id": "1-4-4",
"name": "叶子节点2244",
"route": "1,2,6"
}],
"id": "1-1",
"name": "叶子节点221",
"route": "1,2"
}, {
"id": "1-2",
"name": "叶子节点222",
"route": "1,3"
}, {
"id": "1-3",
"name": "叶子节点223",
"route": "1,4"
}, {
"id": "1-4",
"name": "叶子节点224",
"route": "1,5"
}],
"id": "1",
"name": "父节点22折叠",
"route": "1"
}, {
"children": [{
"id": "2-1",
"name": "叶子节点231",
"route": "2,2"
}, {
"id": "2-2",
"name": "叶子节点232",
"route": "2,3"
}, {
"id": "2-3",
"name": "叶子节点233",
"route": "2,4"
}, {
"id": "2-4",
"name": "叶子节点234",
"route": "2,5"
}],
"id": "2",
"name": "父节点23 - 折叠",
"route": "2"
}, {
"children": [{
"children": [{
"id": "2-1-3",
"name": "叶子节点2313",
"route": "3,2,3"
}, {
"id": "2-2-3",
"name": "叶子节点2323",
"route": "3,2,4"
}, {
"id": "2-3-3",
"name": "叶子节点2333",
"route": "3,2,5"
}, {
"id": "2-4-3",
"name": "叶子节点2343",
"route": "3,2,6"
}],
"id": "2-1-1",
"name": "叶子节点232",
"route": "3,2"
}],
"id": "3",
"name": "父节点24 - 折叠",
"route": "3"
}]