在系统开发过程中,可能会碰到一些需求,需要构建树形结构,当用两个字段造树时遇到各自不同的问题。虽然可以通过数据库SQL查询,但我们一般都是通过SQL一次性查询出所有数据,在程序中处理成树形结构。仅记录参考使用!
常见问题:
1、死循环
2、数据重复
3、父级数据丢失等
通过自己的实例经理总结了如下方法
@Data
public class Sx_testListVO{
@JSONField(name = "fullname")
private String fullname;
@JSONField(name = "subname")
private String subname;
@JSONField(name = "children")
private List<Sx_testListVO> children;
//获取父级
List<Sx_testListVO> realListVo = new ArrayList<>();
List<Sx_testListVO> listhas = new ArrayList<>();//创建一个存储list,遍历过就添加进来
for (int i = 0; i < listVO.size(); i++) {
Sx_testListVO item = listVO.get(i);
if (StringUtil.isEmpty(item.getFullname()) || "[]".equals(item.getFullname())) {
realListVo.add(findChild(item, listVO,listhas));//递归获取子集
//递归方法
private static Sx_testListVO findChild(Sx_testListVO node, List<Sx_testListVO> list,List<Sx_testListVO> listhas) {
listhas.add(node);//添加已遍历过的对象
for (int i = 0; i < list.size(); i++) {
Sx_testListVO n = list.get(i);
if(listhas.contains(n)) {
continue;
if (!StringUtil.isEmpty(node.getSubname()) && node.getSubname().equals(n.getFullname())) {
if (node.getChildren() == null) {
node.setChildren(new ArrayList<>());
node.getChildren().add(findChild(n, list, listhas));
return node;
以上方法可解决遇到的相关问题,可参考。
import lombok.Getter;
import lombok.Setter;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import java.util.ArrayList;
import java.util.List;
* 将一个list对象转换为树结构,并递归遍历树结构所有分支
public class tranLink {
protected String id;
protected String pid;
protected List<? super SuperTree> children = new ArrayList<>();
2.工具类
public static <V extends SuperTree> List<V> getTree(@Nullable List<V> l
怎么及时发现程序陷入死循环?
首先根据死循环的判断依据:周期性调用相同方法名传入相同参数。那么只需要判断这个方法连续或非连续(多线程)传入的参数是不是和之前一样就可以了,这里我定义了两个静态参数,一个是这个方法当前传入的参数(这里暂时定为一个),另一个参数是连续传入的参数的次数,只要传入参数和当前参数不一样,那么就将当前参数进行修改覆盖,计数置为0。这样在计数达到一定值(10或20或100,具体视业务的复杂程度)的时候就判定此方法陷入了死循环。
发现死循环之后需要让程序执行什么操作呢?
在发现死循环之后及时
1. 创建一个空的树形结构对象,用于存储转换后的结果。
2. 遍历数组,对于每一个元素,判断它是否为根节点,即它的父节点是否为 null 或 undefined。如果是根节点,则将其作为树形结构的根节点,否则将其作为某个节点的子节点。
3. 如果当前元素不是根节点,则需要遍历树形结构,找到它应该作为子节点的节点。可以通过递归实现这一步骤,从根节点开始遍历整个树形结构,找到第一个满足条件的节点,将当前元素作为它的子节点。
4. 重复步骤 2 和 3,直到数组中的所有元素都被处理完毕。
以下是一个示例代码:
```javascript
function arrayToTree(arr, parentId) {
const tree = [];
for (let i = 0; i < arr.length; i++) {
const node = arr[i];
if (node.parentId === parentId) {
const children = arrayToTree(arr, node.id);
if (children.length > 0) {
node.children = children;
tree.push(node);
return tree;
在上面的代码中,`arr` 是需要转换的数组,`parentId` 是当前节点的父节点 ID。在遍历数组时,判断当前节点的 `parentId` 是否等于 `parentId`,如果是,则将其加入到树形结构中,并递归处理它的子节点。如果不是,则跳过该节点。
需要注意的是,上面的代码并没有对数组进行排序,如果需要按照某种顺序构建树形结构,需要对数组进行排序。另外,上面的代码只是一个简单的示例,实际应用中可能需要进行一些优化,例如使用哈希表存储节点,避免重复遍历等。