List结构数据组装成树结构实现方式

本文记录List结构数据组装成树结构实现.


使用场景

通过查询数据库中具有父子关系的结构数据,将获得的List数据转换为Tree结构的数据,一般用于前端多级树展示

技术点

  • 递归
  • 双层for循环
  • 高速缓存Map

效果展示

[{
	"id": "1",
	"name": "广州",
	"parentId": "0",
	"children": [{
		"id": "3",
		"name": "天河区",
		"parentId": "1",
		"children": [{
			"id": "6",
			"name": "石牌",
			"parentId": "3",
			"children": [{
				"id": "7",
				"name": "百脑汇",
				"parentId": "6"
			}]
		}]
	}, {
		"id": "4",
		"name": "越秀区",
		"parentId": "1"
	}, {
		"id": "5",
		"name": "黄埔区",
		"parentId": "1"
	}]
}, {
	"id": "2",
	"name": "深圳",
	"parentId": "0",
	"children": [{
		"id": "8",
		"name": "南山区",
		"parentId": "2",
		"children": [{
			"id": "10",
			"name": "科技园",
			"parentId": "8"
		}]
	}, {
		"id": "9",
		"name": "宝安区",
		"parentId": "2"
	}]
}]

实现代码

树节点定义:

import com.alibaba.fastjson.annotation.JSONType;
import lombok.Data;

import java.io.Serializable;
import java.util.List;

/**
 * TODO 树节点
 *
 * @date 2019/8/19 17:54
 **/
@Data
@JSONType(orders = {"id","name","parentId","children"})
public class TreeNode implements Serializable{
    private String id;

    private String parentId;

    private String name;

    private List<TreeNode> children;

    public TreeNode(String id, String name, String parentId) {
        this.id = id;
        this.name = name;
        this.parentId = parentId;
    }

    public TreeNode(String id, String name, TreeNode parent) {
        this.id = id;
        this.name = name;
        this.parentId = parent.getId();
    }

    public TreeNode(TreeNode node) {
        this.id = node.getId();
        this.name = node.getName();
        this.parentId = node.getParentId();
    }
}

树组装类:

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import org.junit.Test;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * TODO 树构造器
 *
 * @date 2019/8/19 17:55
 **/
public class TreeBuilder {

    /**
     * TODO 双层循环实现建树,对传入的树节点列表无排序要求
     * @param treeNodes 传入的树节点列表
     * @return
     */
    public static List<TreeNode> bulidByLoop(List<TreeNode> treeNodes) {

        List<TreeNode> trees = new ArrayList<TreeNode>();
        for (TreeNode treeNode : treeNodes) {
            /*
             * 根节点的父Id为0,且不要求仅有唯一的根
              */
            if ("0".equals(treeNode.getParentId())) {
                trees.add(treeNode);
            }
            for (TreeNode it : treeNodes) {
                if (it.getParentId() == treeNode.getId()) {
                    if (treeNode.getChildren() == null) {
                        treeNode.setChildren(new ArrayList<TreeNode>());
                    }
                    treeNode.getChildren().add(it);
                }
            }
        }
        return trees;
    }

    /**
     * TODO 使用递归方法建树,对传入的树节点列表无排序要求
     * @param treeNodes
     * @return
     */
    public static List<TreeNode> buildByRecursive(List<TreeNode> treeNodes) {
        List<TreeNode> trees = new ArrayList<TreeNode>();
        for (TreeNode treeNode : treeNodes) {
            // 根节点的父Id为0,且不要求仅有唯一的根
            if ("0".equals(treeNode.getParentId())) {
                trees.add(findChildren(treeNode,treeNodes));
            }
        }
        return trees;
    }

    /**
     * TODO 递归查找子节点
     * @param treeNodes
     * @return
     */
    public static TreeNode findChildren(TreeNode treeNode,List<TreeNode> treeNodes) {
        for (TreeNode it : treeNodes) {
            if(treeNode.getId().equals(it.getParentId())) {
                if (treeNode.getChildren() == null) {
                    treeNode.setChildren(new ArrayList<TreeNode>());
                }
                treeNode.getChildren().add(findChildren(it,treeNodes));
            }
        }
        return treeNode;
    }

    /**
     * TODO 通过Map缓存生成树
     * @param dataList 经过排序的集合,要求父节点必须位于集合第一个元素,且仅能存在唯一的根节点
     * @return tree.TreeNode
     **/
    public static TreeNode bulidByMapLink(List<TreeNode> dataList) {
        if (null == dataList || 0 == dataList.size()) {
            return null;
        }
        // 节点缓存
        Map<String, TreeNode> linkTree = new HashMap<String, TreeNode>();
        TreeNode temp = new TreeNode(dataList.get(0));
        // 缓存树结构
        linkTree.put(temp.getId(), temp);
        // 遍历数据除首条外的数据,建立节点关联关系
        for (int i = 1; i < dataList.size(); i++) {
            TreeNode node = new TreeNode(dataList.get(i));
            if (null != linkTree.get(dataList.get(i).getParentId())) {
                // 缓存中已存在相关父节点,子节点
                if (null == linkTree.get(dataList.get(i).getParentId()).getChildren()) {
                    // 缓存中子节点不存在
                    linkTree.get(dataList.get(i).getParentId()).setChildren(new ArrayList<TreeNode>());
                }
                linkTree.get(dataList.get(i).getParentId()).getChildren().add(node);
            }
            linkTree.put(node.getId(), node);
        }
        TreeNode reTree = linkTree.get(temp.getId());
        linkTree.clear();
        return reTree;
    }

    /**
     * TODO 为双层循环,递归方法实现建树组装集合
     * @param
     * @return java.util.List<tree.TreeNode>
     * @date 2019/8/20 10:44
     **/
    public static List<TreeNode> initList(){
        TreeNode treeNode1 = new TreeNode("1","广州","0");
        TreeNode treeNode2 = new TreeNode("2","深圳","0");

        TreeNode treeNode3 = new TreeNode("3","天河区",treeNode1);
        TreeNode treeNode4 = new TreeNode("4","越秀区",treeNode1);
        TreeNode treeNode5 = new TreeNode("5","黄埔区",treeNode1);
        TreeNode treeNode6 = new TreeNode("6","石牌",treeNode3);
        TreeNode treeNode7 = new TreeNode("7","百脑汇",treeNode6);

        TreeNode treeNode8 = new TreeNode("8","南山区",treeNode2);
        TreeNode treeNode9 = new TreeNode("9","宝安区",treeNode2);
        TreeNode treeNode10 = new TreeNode("10","科技园",treeNode8);

        List<TreeNode> list = new ArrayList<TreeNode>();
        list.add(treeNode1);
        list.add(treeNode2);
        list.add(treeNode3);
        list.add(treeNode4);
        list.add(treeNode5);
        list.add(treeNode6);
        list.add(treeNode7);
        list.add(treeNode8);
        list.add(treeNode9);
        list.add(treeNode10);
        return list;
    }

    /**
     * TODO 为通过Map缓存实现建树组装集合
     * @param
     * @return java.util.List<tree.TreeNode>
     * @date 2019/8/20 10:45
     **/
    public static List<TreeNode> initListByMapLink(){
        TreeNode treeNode0_t = new TreeNode("0","中国","-1");

        TreeNode treeNode1_t = new TreeNode("1","广州",treeNode0_t);
        TreeNode treeNode2_t = new TreeNode("2","深圳",treeNode0_t);

        TreeNode treeNode3_t = new TreeNode("3","天河区",treeNode1_t);
        TreeNode treeNode4_t = new TreeNode("4","越秀区",treeNode1_t);
        TreeNode treeNode5_t = new TreeNode("5","黄埔区",treeNode1_t);
        TreeNode treeNode6_t = new TreeNode("6","石牌",treeNode3_t);
        TreeNode treeNode7_t = new TreeNode("7","百脑汇",treeNode6_t);

        TreeNode treeNode8_t = new TreeNode("8","南山区",treeNode2_t);
        TreeNode treeNode9_t = new TreeNode("9","宝安区",treeNode2_t);
        TreeNode treeNode10_t = new TreeNode("10","科技园",treeNode8_t);

        List<TreeNode> list_t = new ArrayList<TreeNode>();
        list_t.add(treeNode0_t);
        list_t.add(treeNode1_t);
        list_t.add(treeNode2_t);
        list_t.add(treeNode3_t);
        list_t.add(treeNode4_t);
        list_t.add(treeNode5_t);
        list_t.add(treeNode6_t);
        list_t.add(treeNode7_t);
        list_t.add(treeNode8_t);
        list_t.add(treeNode9_t);
        list_t.add(treeNode10_t);
        return list_t;
    }

    @Test
    public void testBulidByLoop(){
        List<TreeNode> treeNodes = initList();
        List<TreeNode> trees_0 = TreeBuilder.bulidByLoop(treeNodes);
        // 指定Json转换时保持Key顺序,Key顺序由@JSONType(orders)指定
        System.out.println("trees[0]:"+ JSONObject.toJSONString(trees_0, SerializerFeature.SortField));
    }

    @Test
    public void testBulidByRecursive(){
        List<TreeNode> treeNodes = initList();
        List<TreeNode> trees_1 = TreeBuilder.buildByRecursive(treeNodes);
        System.out.println("trees[1]:"+ JSONObject.toJSONString(trees_1, SerializerFeature.SortField));
    }

    @Test
    public void testBulidByMapLink(){
        List<TreeNode> treeNodes = initListByMapLink();
        TreeNode trees_2 = TreeBuilder.bulidByMapLink(treeNodes);
        System.out.println("trees[2]:"+ JSONObject.toJSONString(trees_2, SerializerFeature.SortField));
    }
}



  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
List数据转换成树结构的基本思路是首先遍历List,将其中每个节点的父子关系建立起来,然后从根节点开始递归构建整个树形结构。 具体实现步骤如下: 1. 定义节点类,包含节点id、节点名称和子节点列表等属性。 ``` public class TreeNode { private String id; private String name; private List<TreeNode> children; // getter和setter方法 // ... } ``` 2. 遍历List,将每个节点的父子关系建立起来,可以使用Map来存储节点id和对应的节点对象,便于查找父节点。 ``` Map<String, TreeNode> map = new HashMap<>(); for (TreeNode node : list) { map.put(node.getId(), node); String parentId = node.getParentId(); if (parentId != null) { TreeNode parent = map.get(parentId); if (parent != null) { parent.getChildren().add(node); } } } ``` 3. 找到根节点,开始递归构建整个树形结构。 ``` public static TreeNode buildTree(List<TreeNode> list) { // 构建Map,方便查找节点 Map<String, TreeNode> map = new HashMap<>(); for (TreeNode node : list) { map.put(node.getId(), node); } // 找到根节点 TreeNode root = null; for (TreeNode node : list) { if (node.getParentId() == null) { root = node; break; } } // 从根节点开始递归构建整个树形结构 buildSubTree(root, map); return root; } private static void buildSubTree(TreeNode node, Map<String, TreeNode> map) { List<TreeNode> children = node.getChildren(); if (children == null) { return; } // 遍历子节点,递归构建子树 for (TreeNode child : children) { buildSubTree(child, map); } // 根据子节点的顺序重新排序 children.sort(Comparator.comparing(TreeNode::getName)); } ``` 以上就是将List数据转换成树结构的基本实现方法。需要注意的是,这里的代码只是一个简单的示例,实际情况下可能需要根据具体的业务需求进行修改和优化。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值