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));
    }
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章