1. 程式人生 > >將伺服器後臺返回的資料轉換為樹結構資料給前臺

將伺服器後臺返回的資料轉換為樹結構資料給前臺

       我們在前臺向後臺請求資料時可能會希望能得到一個樹結構的資料結構,方便我們前臺獲取和使用,也能使得資料結構清晰,一目瞭然,樹結構一般情況在我遇到的專案中都是某個表的自關聯,使用到子父節點的關係,我們一般情況下可能會有這樣的需求,獲取全部資料或根據父節點獲取子節點所有資料,如果我們直接返回資料,會讓資料顯得很亂,沒有層次關係,所以我們需要使用樹結構,我們先看一張圖瞭解一下樹結構:我這裡隨便找一張圖瞭解一下即可


我們再看一張自關聯的資料庫表,最常見的就是地區表的自連線,例如深圳下面有南山區,廣州下面有天河區


接下來我們就來寫個例子測試一下:一般我們採用兩種方式來轉換為樹:1.迴圈 2.遞迴

/**
 * @Auther: HeJD
 * @Date: 2018/7/6 14:43
 * @Description:
 */

import java.util.List;

/**
 * Created by Massive on 2016/12/26.
 */
public class TreeNode {

    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.parentId = parentId;
        this.name = name;
    }
    public TreeNode(String id, String name, TreeNode parent) {
        this.id = id;
        this.parentId = parent.getId();
        this.name = name;
    }


    public String getParentId() {
        return parentId;
    }

    public void setParentId(String parentId) {
        this.parentId = parentId;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public List<TreeNode> getChildren() {
        return children;
    }

    public void setChildren(List<TreeNode> children) {
        this.children = children;
    }

    @Override
    public String toString() {
        return "TreeNode{" +
                "id='" + id + '\'' +
                ", parentId='" + parentId + '\'' +
                ", name='" + name + '\'' +
                ", children=" + children +
                '}';
    }

}

/**
 * @Auther: HeJD
 * @Date: 2018/7/6 14:44
 * @Description:
 */

import java.util.ArrayList;
import java.util.List;

/**
 * Created by Massive on 2016/12/26.
 */
public class TreeBuilder {

    /**
     * 兩層迴圈實現建樹
     * @param treeNodes 傳入的樹節點列表
     * @return
     */
    public static List<TreeNode> bulid(List<TreeNode> treeNodes) {

        List<TreeNode> trees = new ArrayList<TreeNode>();

        for (TreeNode treeNode : treeNodes) {

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

    /**
     * 使用遞迴方法建樹
     * @param treeNodes
     * @return
     */
    public static List<TreeNode> buildByRecursive(List<TreeNode> treeNodes) {
        List<TreeNode> trees = new ArrayList<TreeNode>();
        for (TreeNode treeNode : treeNodes) {
            if ("0".equals(treeNode.getParentId())) {
            trees.add(findChildren(treeNode,treeNodes));
        }
    }
        return trees;
    }

    /**
     * 遞迴查詢子節點
     * @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;
    }



    public static void main(String[] args) {

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

        //第一種方式
        List<TreeNode> trees = TreeBuilder.bulid(list);

        //第二種方式
        List<TreeNode> trees_ = TreeBuilder.buildByRecursive(list);

    }

}

具體的執行邏輯和執行過程,可以將程式複製下來打斷點一步一步執行,這樣就可知道迴圈和遞迴分別是如何實現資料變成樹結構的,下面貼一張我除錯的資料內容,執行上面任何一種方法後的資料都是一樣的。


迴圈的邏輯是這樣的,假設第一個迴圈到的資料是廣州:先查詢廣州下面所有的子節點並新增進來,所以第一遍就變成了


然後接著第二遍迴圈,假設第二遍迴圈到的資料是天河(當然也可能是其他的),那麼邏輯就如下圖,接著上面


遞迴的邏輯是,假設第一個迴圈到的資料是廣州,那麼就遞迴遍歷所有廣州下面的子節點,大概的流程圖如下