多层级树结构封装
问题描述
- 实际工作可能会遇到比如子节点的排序很不规范,但是上一级是存在的。
如图,ba结尾节点,再后续又多次出现说明,其公用同一级母节点,这样就的效果组装成树结构是比较麻烦的。
代码实现
前提
- 本案例设计到根节点 根是年份,按照年份进行划分
- 查出所有年份存入redis->再根据年份查找不同年份对应树存入redis
- 从而降低数据库压力
代码
mybatis
<!--mybatis-->
<select id="getYearList" resultType="string">
SELECT distinct cataYear
FROM p_cata_tree
where cataYear < 2020
</select>
<select id="getTreeByYear" parameterType="String" resultType="stcsm.feasiblescheme.model.entity.StcsmProjectClass">
SELECT node_id id, node_id, cataName, parentNodeId
FROM p_cata_tree
where cataYear = #{year}
order by cataCode asc
</select>
service
private final static String HEAD = "0";
private final static String YEAR_DETAIL = "project:class:detail:";
private final static String YEAR_LIST = "project:years:list:";
@Autowired
private StcsmProjectClassMapper stcsmProjectClassMapper;
@PostConstruct
@Override
public void init() {
//获取2020以下所有年份
List<String> yearList = stcsmProjectClassMapper.getYearList();
redisTemplate.opsForValue().set(YEAR_DETAIL,yearList);
//遍历年份查询
yearList.stream().forEach(year -> {
ProjectCataTree projectCataTree = new ProjectCataTree(UUID.randomUUID().toString(), year);
//存放节点下标层级
Map<String, String> map = new HashMap<>();
//根据年份查询
List<StcsmProjectClass> treeByYear = stcsmProjectClassMapper.getTreeByYear(year);
//遍历集合
List<ProjectCataTree> list = new ArrayList<>();
treeByYear.stream().forEach(pCataTree -> {
//头节点判断 0为头节点
if (pCataTree.getParentNodeId().equals(HEAD)) {
//key 头节点id value 头节点对应集合下标
map.put(pCataTree.getNodeId(), String.valueOf(list.size()));
//添加集合
list.add(new ProjectCataTree(pCataTree.getId(), year, pCataTree.getNodeId(), pCataTree.getCataName()));
} else if (map.containsKey(pCataTree.getParentNodeId())) {
//子节点
//集合节点
String node = map.get(pCataTree.getParentNodeId());
//子节点存储
int index = addChildren(list, node, new ProjectCataTree(pCataTree.getId(), year, pCataTree.getNodeId(), pCataTree.getCataName()));
node = node + "-" + index;
map.put(pCataTree.getNodeId(), node);
}
});
projectCataTree.setChildren(list);
//存入redis
redisTemplate.opsForValue().set(YEAR_DETAIL + year, JSON.toJSONString(projectCataTree));
map.clear();
});
}
/**
* 插入孩子节点
*
* @param pTreeList
* @param node
* @param tree
* @return
*/
int addChildren(List<ProjectCataTree> pTreeList, String node, ProjectCataTree tree) {
//切分节点找到对应根节点位置
String[] nodes = node.split("-");
ProjectCataTree pTree = null;
for (int i = 0; i < nodes.length; i++) {
//初始化赋值 从集合中拿PTree
//后续不断遍历 到母节点
if (i == 0) {
pTree = pTreeList.get(Integer.valueOf(nodes[i]));
} else {
pTree = pTree.getChildren().get(Integer.valueOf(nodes[i]));
}
}
//插入新数据
pTree.getChildren().add(tree);
//返回插入位置
return pTree.getChildren().size() - 1;
}
实体层
- ProjectCataTree
/**
* @Author: fl
* @Date: 2022/07/22/11:08
* @Description:类别展示
*/
public class ProjectCataTree implements Serializable {
private static final long serialVersionUID = 1L;
private String key;
private String cataYear;
private String nodeId;
private String title;
private String value;
private List<ProjectCataTree> children = new ArrayList<>();
public ProjectCataTree(String key,String cataYear) {
this.key= key;
this.cataYear = cataYear;
this.title=cataYear;
this.value=this.key;
}
public ProjectCataTree(String key, String cataYear, String nodeId, String title) {
this.key = key;
this.cataYear = cataYear;
this.nodeId = nodeId;
this.title = title;
this.value=key;
}
public String getCataYear() {
return cataYear;
}
public void setCataYear(String cataYear) {
this.cataYear = cataYear;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public List<ProjectCataTree> getChildren() {
return children;
}
public void setChildren(List<ProjectCataTree> children) {
this.children = children;
}
public static long getSerialVersionUID() {
return serialVersionUID;
}
public String getNodeId() {
return nodeId;
}
public void setNodeId(String nodeId) {
this.nodeId = nodeId;
}
}
- StcsmProjectClass
/**
* 类别
*
* @Author: fl
* @Date: 2022/07/05/11:12
* @Description:
*/
public class StcsmProjectClass implements Serializable {
private static final long serialVersionUID = 1L;
private String id;
/**
* uuid
*/
private String nodeId;
/**
* 类别名称
*/
private String cataName;
/**
* 根节点id
*/
private String parentNodeId;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getNodeId() {
return nodeId;
}
public void setNodeId(String nodeId) {
this.nodeId = nodeId;
}
public String getCataName() {
return cataName;
}
public void setCataName(String cataName) {
this.cataName = cataName;
}
public String getParentNodeId() {
return parentNodeId;
}
public void setParentNodeId(String parentNodeId) {
this.parentNodeId = parentNodeId;
}
}
c void setCataName(String cataName) {
this.cataName = cataName;
}
public String getParentNodeId() {
return parentNodeId;
}
public void setParentNodeId(String parentNodeId) {
this.parentNodeId = parentNodeId;
}
}