有个需求需要后端生成json树,找了一个大佬的文章,没看懂,自己写一个吧
java+mysql递归拼接树形JSON列表_鬼畜的稀饭的博客-CSDN博客
新建`TestNode.java`类
package info;
import lombok.Data;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import java.util.List;
@Data
public class TestNode
{
private String menuId;
private String name;
private String pid;
private List<TestNode> subMenu;
private String fullName;
private Integer level;
private Boolean hasKeyword;
@Override
public String toString()
{
return ToStringBuilder.reflectionToString(this, ToStringStyle.JSON_STYLE);
}
}
新建test类
import com.alibaba.fastjson.JSONArray;
import info.TestNode;
import org.junit.jupiter.api.Test;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
public class FileTest
{
private List<TestNode> nodes = new ArrayList<>();
@Test
public void testMenu()
{
String str = "[{\"menuId\":\"1001\",\"pid\":null,\"name\":\"商品类目\"}, {\"menuId\":\"1002\",\"pid\":\"1001\",\"name\":\"日用品\"}, {\"menuId\":\"1003\",\"pid\":\"1001\",\"name\":\"食品\"}, {\"menuId\":\"1004\",\"pid\":\"1002\",\"name\":\"洗发水\"}, {\"menuId\":\"1005\",\"pid\":\"1004\",\"name\":\"飘柔\"},{\"menuId\":\"1006\",\"pid\":\"1002\",\"name\":\"化妆品\"}]";
nodes = JSONArray.parseArray(str, TestNode.class);
List<TestNode> treeNodes = new ArrayList<>();
for (int i = 0; i < nodes.size(); i++)
{
TestNode rootNode = nodes.get(i);
rootNode.setSubMenu(getChildNodes(rootNode));
treeNodes.add(rootNode);
nodes.remove(rootNode);
i --;
}
System.out.println(treeNodes);
}
private List<TestNode> getChildNodes(TestNode pNode)
{
List<TestNode> child = new LinkedList<>();
for (int i = 0; i < this.nodes.size(); i++)
{
TestNode node = nodes.get(i);
if (pNode.getMenuId().equals(node.getPid()))
{
node.setSubMenu(getChildNodes(node));
child.add(node);
this.nodes.remove(node);
i --;
}
}
return child;
}
}
输出结果
[
{
"menuId": "1001",
"name": "商品类目",
"pid": null,
"subMenu":
[
{
"menuId": "1002",
"name": "日用品",
"pid": "1001",
"subMenu":
[
{
"menuId": "1004",
"name": "洗发水",
"pid": "1002",
"subMenu":
[
{
"menuId": "1005",
"name": "飘柔",
"pid": "1004",
"subMenu":
[]
}
]
},
{
"menuId": "1006",
"name": "化妆品",
"pid": "1002",
"subMenu":
[]
}
]
},
{
"menuId": "1003",
"name": "食品",
"pid": "1001",
"subMenu":
[]
}
]
}
]
------------------------------------------------------------分隔符------------------------------------------------------------
package test;
import com.alibaba.fastjson.JSONArray;
import org.apache.commons.lang3.StringUtils;
import org.junit.Test;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.stream.Collectors;
public class TestNode2 {
/**
* 组装树形结构
*/
@Test
public void testMenu() {
String str = "[{\"menuId\":\"1001\",\"pid\":null,\"name\":\"商品类目\"}, {\"menuId\":\"1002\",\"pid\":\"1001\",\"name\":\"日用品\"}, {\"menuId\":\"1003\",\"pid\":\"1001\",\"name\":\"食品\"}, {\"menuId\":\"1004\",\"pid\":\"1002\",\"name\":\"洗发水\"}, {\"menuId\":\"1005\",\"pid\":\"1004\",\"name\":\"飘柔\"},{\"menuId\":\"1006\",\"pid\":\"1002\",\"name\":\"化妆品\"}]";
List<TestNode> nodes = JSONArray.parseArray(str, TestNode.class);
//父级节点列表
List<TestNode> parentList = nodes.stream().filter(v -> StringUtils.isBlank(v.getPid())).collect(Collectors.toList());
//根据父元素分组
Map<String, List<TestNode>> nodeMap = nodes.stream().filter(v -> StringUtils.isNotBlank(v.getPid())).collect(Collectors.groupingBy(TestNode::getPid));
//根据menuId
Map<String, TestNode> singleNodeMap = nodes.stream().collect(Collectors.toMap(TestNode::getMenuId, v -> v));
for (TestNode node : nodes) {
StringBuilder fullName = new StringBuilder();
int level = setFullNameAddGetLevel(node, fullName, singleNodeMap, 0);
node.setFullName(StringUtils.removeFirst(fullName.toString(), "-"));
node.setLevel(level);
}
long start = System.currentTimeMillis();
for (TestNode node : parentList) {
getChildNodes(node, nodeMap);
}
System.out.println(parentList);
System.out.println(System.currentTimeMillis() - start);
}
/**
* 判断是否具有最底层节点
*/
@Test
public void testNullMenu() {
String str = "[{\"menuId\":\"1001\",\"pid\":null,\"name\":\"商品类目\"}, {\"menuId\":\"1002\",\"pid\":\"1001\",\"name\":\"日用品\"}, {\"menuId\":\"1003\",\"pid\":\"1001\",\"name\":\"食品\"}, {\"menuId\":\"1004\",\"pid\":\"1002\",\"name\":\"洗发水\"}, {\"menuId\":\"1005\",\"pid\":\"1004\",\"name\":\"飘柔\"},{\"menuId\":\"1006\",\"pid\":\"1002\",\"name\":\"化妆品\"}]";
List<TestNode> nodes = JSONArray.parseArray(str, TestNode.class);
// 单map
Map<String, TestNode> singleNodeMap = nodes.stream().collect(Collectors.toMap(TestNode::getMenuId, v -> v));
for (TestNode node : nodes) {
StringBuilder fullName = new StringBuilder();
int level = setFullNameAddGetLevel(node, fullName, singleNodeMap, 0);
node.setFullName(StringUtils.removeFirst(fullName.toString(), "-"));
node.setLevel(level);
}
//https://blog.csdn.net/zhuhao717/article/details/47444763
//HashMap是按照HashCode 排序,莫名其妙的顺序。
//TreeMap是按照自身的顺序排序,比如数字的话,按照数字升序,ascII等。
//LinkedHashMap是按照先进先出的顺序。
TreeMap<Integer, List<TestNode>> levelMap = nodes.stream().collect(Collectors.groupingBy(TestNode::getLevel, TreeMap::new, Collectors.toList()));
//获取最底层列表
List<TestNode> maxLevelList = levelMap.get(levelMap.size());
for (TestNode testNode : maxLevelList) {
checkHasKeyword(testNode, singleNodeMap);
}
System.out.println(nodes);
}
private void checkHasKeyword(TestNode node, Map<String, TestNode> nodeMap) {
node.setHasKeyword(true);
if (StringUtils.isBlank(node.getPid())) {
return;
}
TestNode parentNode = nodeMap.get(node.getPid());
checkHasKeyword(parentNode, nodeMap);
}
private int setFullNameAddGetLevel(TestNode node, StringBuilder fullName, Map<String, TestNode> nodeMap, int level) {
level++;
fullName.insert(0, String.format("-%s", node.getName()));
if (StringUtils.isBlank(node.getPid())) {
return level;
}
TestNode parentNode = nodeMap.get(node.getPid());
return setFullNameAddGetLevel(parentNode, fullName, nodeMap, level);
}
private void getChildNodes(TestNode pNode, Map<String, List<TestNode>> nodeMap) {
List<TestNode> childNodes = nodeMap.get(pNode.getMenuId());
if (childNodes == null) {
return;
}
pNode.setSubMenu(childNodes);
for (TestNode childNode : childNodes) {
getChildNodes(childNode, nodeMap);
}
}
}
---------------------------------------------------------分隔符-------------------------------------------------------------
获取自己负责的团队及子团队
package com.hxg.core.test.model;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Team {
/**
* 团队uid
*/
private String uid;
/**
* 团队名称
*/
private String teamName;
/**
* 负责人uid
*/
private String leaderUid;
/**
* 父团队uid
*/
private String parentUid;
}
package test;
import com.hxg.core.test.model.Team;
import org.junit.Test;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class TestTeam {
@Test
public void test() {
List<Team> teams = new ArrayList<>();
Team team1 = new Team("1001", "团队1", "2001", "");
Team team2 = new Team("1002", "团队2", "2002", "1001");
Team team3 = new Team("1003", "团队3", "2003", "1001");
Team team4 = new Team("1004", "团队4", "2004", "1002");
Team team5 = new Team("1005", "团队5", "2005", "1004");
Team team6 = new Team("1006", "团队6", "2001", "");
Team team7 = new Team("1007", "团队7", "2002", "");
Team team8 = new Team("1008", "团队8", "2005", "1005");
Team team9 = new Team("1009", "团队9", "2006", "1007");
teams.add(team1);
teams.add(team2);
teams.add(team3);
teams.add(team4);
teams.add(team5);
teams.add(team6);
teams.add(team7);
teams.add(team8);
teams.add(team9);
Set<String> leaderTeamSet = new HashSet<>();
leaderTeamSet.add("1001");
//前提:父团队的uid比子团队的uid大
for (Team team : teams) {
if (leaderTeamSet.contains(team.getUid()) || leaderTeamSet.contains(team.getParentUid())) {
leaderTeamSet.add(team.getUid());
System.out.println(team.getTeamName());
}
}
}
}
如果有隐藏bug或者性能优化建议,还请各位路过大佬不吝赐教。