只用一次集合遍历实现树形结构,非递归方式

       一般情况下,我们想要实现这种无限层级的树形结构,都是采用递归的方式,但是递归比较占用内存,也容易导致栈溢出,于是只能尝试其它的方法。

        下面采用的方式,只需要一次集合的遍历就可以实现树形的结构。

 先手动编造一个树形结构的数据:

这是一个无序的树形结构数据的 json 格式:

[{"nodeId" : "700","nodeDesc" : "节点700","parentNodeId" : ""},{"nodeId" : "300","nodeDesc" : "节点300","parentNodeId" : ""},{"nodeId" : "500","nodeDesc" : "节点500","parentNodeId" : ""},{"nodeId" : "100","nodeDesc" : "节点100","parentNodeId" : ""},{"nodeId" : "400","nodeDesc" : "节点400","parentNodeId" : ""},{"nodeId" : "800","nodeDesc" : "节点800","parentNodeId" : ""},{"nodeId" : "200","nodeDesc" : "节点200","parentNodeId" : ""},{"nodeId" : "700-001","nodeDesc" : "节点700-001","parentNodeId" : "700"},{"nodeId" : "700-002","nodeDesc" : "节点700-002","parentNodeId" : "700"},{"nodeId" : "700-003","nodeDesc" : "节点700-003","parentNodeId" : "700"},{"nodeId" : "700-004","nodeDesc" : "节点700-004","parentNodeId" : "700"},{"nodeId" : "700-005","nodeDesc" : "节点700-005","parentNodeId" : "700"},{"nodeId" : "700-006","nodeDesc" : "节点700-006","parentNodeId" : "700"},{"nodeId" : "700-003-002","nodeDesc" : "节点700-003-002","parentNodeId" : "700-003"},{"nodeId" : "700-003-001","nodeDesc" : "节点700-003-001","parentNodeId" : "700-003"},{"nodeId" : "700-003-002-001","nodeDesc" : "节点700-003-002-001","parentNodeId" : "700-003-002"},{"nodeId" : "700-003-002-003","nodeDesc" : "节点700-003-002-003","parentNodeId" : "700-003-002"},{"nodeId" : "700-003-002-002","nodeDesc" : "节点700-003-002-002","parentNodeId" : "700-003-002"},{"nodeId" : "300-001","nodeDesc" : "节点300-001","parentNodeId" : "300"},{"nodeId" : "300-001-001","nodeDesc" : "节点300-001-001","parentNodeId" : "300-001"},{"nodeId" : "300-001-001-001","nodeDesc" : "节点300-001-001-001","parentNodeId" : "300-001-001"},{"nodeId" : "300-001-001-001-001","nodeDesc" : "节点300-001-001-001-001","parentNodeId" : "300-001-001-001"},{"nodeId" : "300-001-001-001-001-001","nodeDesc" : "节点300-001-001-001-001-001","parentNodeId" : "300-001-001-001-001"},{"nodeId" : "500-003","nodeDesc" : "节点500-003","parentNodeId" : "500"},{"nodeId" : "500-001","nodeDesc" : "节点500-001","parentNodeId" : "500"},{"nodeId" : "500-002","nodeDesc" : "节点500-002","parentNodeId" : "500"},{"nodeId" : "500-003-001","nodeDesc" : "节点500-003-001","parentNodeId" : "500-003"},{"nodeId" : "800-001","nodeDesc" : "节点800-001","parentNodeId" : "800"},{"nodeId" : "100-002","nodeDesc" : "节点100-002","parentNodeId" : "100"},{"nodeId" : "100-001","nodeDesc" : "节点100-001","parentNodeId" : "100"},{"nodeId" : "200-001","nodeDesc" : "节点200-001","parentNodeId" : "200"},{"nodeId" : "400-003","nodeDesc" : "节点400-003","parentNodeId" : "400"},{"nodeId" : "400-002","nodeDesc" : "节点400-002","parentNodeId" : "400"},{"nodeId" : "400-001","nodeDesc" : "节点400-001","parentNodeId" : "400"},{"nodeId" : "100-002-002","nodeDesc" : "节点100-002-002","parentNodeId" : "100-002"},{"nodeId" : "100-002-001","nodeDesc" : "节点100-002-001","parentNodeId" : "100-002"},{"nodeId" : "300-001-001-001-001-002","nodeDesc" : "节点300-001-001-001-001-002","parentNodeId" : "300-001-001-001-001"},{"nodeId" : "300-001-001-002","nodeDesc" : "节点300-001-002","parentNodeId" : "300-001"}
]

      我是在springBoot项目中测试的,通过前端页面展示数形结构的效果。

      这是后端项目结构,前端使用的 ant-design Vue 版。

   

<template><div><a-tree:show-line="true":show-icon="true":tree-data="treeData":replaceFields="{children:'children', title:'nodeDesc', key:'nodeId' }"@select="onSelect"></a-tree></div>
</template><script>import { queryTreeNodeList } from '@/services/myExample';
import { message } from 'ant-design-vue';export default {name: 'lemonTree',data() {return {treeData: []}},created() {queryTreeNodeList().then(response =>{console.log(response, '====response====')this.treeData = response.data.data})},methods: {onSelect(selectedKeys, info) {console.log('selected', selectedKeys, info);// console.log('nodeDesc', info.selectedNodes[0].data.props.nodeDesc);message.info('您点击了:' + info.selectedNodes[0].data.props.nodeDesc);}}
}
</script><style scoped></style>

构建树形结构的核心业务代码,都写在了 service 层的这个方法里:

package com.concat.example.service;import com.alibaba.fastjson2.JSON;
import com.concat.example.entity.LemonTreeEntity;
import org.apache.commons.io.FileUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ResourceUtils;
import org.springframework.util.StringUtils;import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;@Service
public class LemonTreeServiceImpl implements LemonTreeService {@Overridepublic List<LemonTreeEntity> queryAllNodeWithTreeStructure() {List<LemonTreeEntity> dataSource = initLemonTree();// 如果要得到有顺序树状数据结构,则先进行排序操作,并且后面可以通过循环这个有序的集合组装最终的树状结构的数据;List<LemonTreeEntity> lemonTreeNodeList = dataSource.stream().sorted(Comparator.comparing(LemonTreeEntity::getNodeId)).collect(Collectors.toList());// 建立每个节点的 map 映射,方便后面快速查找到对应的节点数据;Map<String, LemonTreeEntity> lemonTreeNodeMap = new HashMap<>();lemonTreeNodeList.stream().forEach(lemonTreeEntity -> {String nodeId = lemonTreeEntity.getNodeId();lemonTreeNodeMap.put(nodeId, lemonTreeEntity);});// 结果集;List<LemonTreeEntity> lemonTreeResult = new ArrayList<>();// 循环这个有序的集合,组装最终的树状结构的数据;lemonTreeNodeList.stream().forEach(lemonTreeEntity -> {String parentNodeId = lemonTreeEntity.getParentNodeId();if (StringUtils.isEmpty(parentNodeId)) {// 说明是树的根节点,直接放在集合中;lemonTreeResult.add(lemonTreeEntity);} else {// 其它都是子节点,需要将每个子节点放在对应的父节点的孩子集合中。LemonTreeEntity parentTreeNodeEntity = lemonTreeNodeMap.get(parentNodeId);List<LemonTreeEntity> children = parentTreeNodeEntity.getChildren();if (children == null) {children = new ArrayList<>();parentTreeNodeEntity.setChildren(children);}children.add(lemonTreeEntity);}});//        String json = JSON.toJSONString(lemonTreeResult);
//        System.out.println("json = " + json);return lemonTreeResult;}private List<LemonTreeEntity> initLemonTree() {File file = null;try {file = ResourceUtils.getFile("classpath:lemon_tree.json");} catch (FileNotFoundException e) {throw new RuntimeException(e);}String json = null;try {json = FileUtils.readFileToString(file, "UTF-8");} catch (IOException e) {throw new RuntimeException(e);}System.out.println("json = " + json);List<LemonTreeEntity> lemonTreeEntityList = JSON.parseArray(json, LemonTreeEntity.class);System.out.println("lemonTreeEntityList = " + lemonTreeEntityList);return lemonTreeEntityList;}
}
package com.concat.example.entity;import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;@Data
@JsonInclude(JsonInclude.Include.NON_EMPTY)
@NoArgsConstructor
public class LemonTreeEntity {private String nodeId;private String nodeDesc;private String parentNodeId;private List<LemonTreeEntity> children;}

 Web项目其它相关:

package com.concat.example.vo;import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import java.io.Serializable;@Data
@Accessors(chain = true)
@NoArgsConstructor
public class MyResponseEntity<T> implements Serializable {private String code;private String message;private T data;}
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.3.6.RELEASE</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.concat.example</groupId><artifactId>spring-initialize-template</artifactId><version>0.0.1-SNAPSHOT</version><name>spring-initialize-template</name><description>Demo project for Spring Boot</description><properties><java.version>8</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>commons-io</groupId><artifactId>commons-io</artifactId><version>2.11.0</version></dependency><!-- 反序列化json字符串 --><dependency><groupId>com.alibaba.fastjson2</groupId><artifactId>fastjson2</artifactId><version>2.0.14</version></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/1533.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Spring 事务管理方案和事务管理器及事务控制的API

目录 一、事务管理方案 1. 修改业务层代码 2. 测试 二、事务管理器 1. 简介 2. 在配置文件中引入约束 3. 进行事务配置 三、事务控制的API 1. PlatformTransactionManager接口 2. TransactionDefinition接口 3. TransactionStatus接口 往期专栏&文章相关导读 …

Spring Boot 中的 @EnableConfigurationProperties 注解

Spring Boot 中的 EnableConfigurationProperties 注解 在 Spring Boot 中&#xff0c;EnableConfigurationProperties 注解是一个非常有用的注解&#xff0c;它可以用于启用对特定配置类的支持。在本文中&#xff0c;我们将深入探讨 EnableConfigurationProperties 注解&…

2023年最新整理网络安全护网蓝队面试题​

如何打击黑灰产工具 全面监控和快速响应&#xff08;溯源&#xff09;&#xff1a;对黑灰进行长期跟进&#xff0c;了解黑灰产工具的传播链条和路径&#xff0c;第一时间捕获活跃的黑灰产工具&#xff08;建立特征词监控&#xff0c;数据取样、交叉分析&#xff09; 建立软件指…

ReentrantReadWriteLock源码

介绍 用一个变量如何维护多种状态 在 ReentrantLock 中&#xff0c;使用 Sync ( 实际是 AQS )的 int 类型的 state 来表示同步状态&#xff0c;表示锁被一个线程重复获取的次数。 但是&#xff0c;读写锁 ReentrantReadWriteLock 内部维护着一对读写锁&#xff0c;如果要用一…

windows下VScode搭建IDApython脚本开发环境遇到的问题

开发环境 IDA pro 7.7 vscode 最新版 python版本 与IDA 自带python 一致 3.8.10 (小版本号也必须要一致) 安装插件 下载 插件仓库的地址&#xff1a;https://github.com/ioncodes/idacode release版本 将插件安装到 IDApath/plugins/ idacode ->setting.py 设置如下:…

SpringMVC原理分析 | Hello程序

&#x1f497;wei_shuo的个人主页 &#x1f4ab;wei_shuo的学习社区 &#x1f310;Hello World &#xff01; SpringMVC Spring MVC 是 Spring 提供的一个基于 MVC 设计模式的轻量级 Web 开发框架&#xff0c;本质上相当于 Servlet&#xff1b; 拥有结构最清晰的 ServletJSPJav…

一步一步学OAK之二: RGB相机控制

今天我们来实现 RGB相机的控制程序&#xff0c;用来控制彩色相机的曝光、灵敏度、白平衡、亮度/色度降噪、 设备端裁剪、相机触发器等。 目录 Setup 1: 创建文件Setup 2: 安装依赖Setup 3: 导入需要的包Setup 4: 全局变量Setup 5: 定义clamp函数Setup 6: 创建pipelineSetup 7:…

蜣螂优化算法(DBO)优化VMD参数,最小包络熵、样本熵、信息熵、排列熵(适应度函数可自行选择,一键修改)包含MATLAB源代码

蜣螂优化算法是华大学沈波教授团队&#xff0c;继麻雀搜索算法(Sparrow Search Algorithm&#xff0c;SSA&#xff09;之后&#xff0c;于2022年11月27日又提出的一种全新的群体智能优化算法。已有很多学者将算法用于实际工程问题中&#xff0c;今天咱们用蜣螂优化算法优化一下…

ASEMI代理光宝光耦LTV-6341的应用与性能分析

编辑-Z 本文将全面深入地探讨光耦LTV-6341的应用与性能。首先&#xff0c;我们将介绍光耦LTV-6341的基本概念和工作原理&#xff0c;然后&#xff0c;我们将详细分析其在电子设备中的应用&#xff0c;接着&#xff0c;我们将对其性能进行深入的分析&#xff0c;最后&#xff0…

python spider 爬虫 之 解析 xpath 、jsonpath、BeautifulSoup (二)

Jsonpath 安装&#xff1a; pip install -i https://pypi.tuna.tsinghua.edu.cn/simple jsonpath 使用&#xff1a;jsonpath 只能解析本地文件&#xff0c;跟xpath不一样 objjson.load(open(‘json文件’&#xff0c;‘r’, encoding‘utf-8’)) json.load(是文件&#xff0c;…

Flink-窗口源码

滚动窗口底层只有一个窗口&#xff0c;每次用for循环&#xff0c;把前面过期的数据移除&#xff0c;留下的数据再进行计算 滑动窗口的时间窗口&#xff0c;是有多个window的&#xff0c;因为有重叠的数据 计数窗口、计数滑动窗口&#xff0c;底层只有一个窗口 会话窗口只有一…

会声会影2023最新六大新功能,会声会影2023序列号能用多少次

会声会影2023版是一款非常实用的视频剪辑软件&#xff0c;该软件能够为广大用户带来丰富的集成化工具&#xff0c;并且优化了工作流程&#xff0c;无论你是新手还是老手都可以快速上手这款软件。会声会影2022永久激活版支持自定义码率设置&#xff0c;用户可以根据自己的需求设…