java構建樹形節點優化


引言:java中構建樹形節點時,數據量小的話,可以隨便些 ,不影響,但是當數據量大了以后,一棵大大的樹,要半天才出來,所以就想着優化一下.

 

樹形節點數據構建:

package me.zhengjie;

import ch.qos.logback.classic.joran.action.RootLoggerAction;
import com.alibaba.fastjson.JSON;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.aspectj.weaver.Lint;
import org.aspectj.weaver.ast.Var;
import org.hibernate.engine.query.spi.ReturnMetadata;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.BeanUtils;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.util.CollectionUtils;
import sun.nio.cs.ext.TIS_620;

import java.io.Serializable;
import java.nio.file.NotDirectoryException;
import java.rmi.dgc.Lease;
import java.util.*;

/**
 * java構建樹形結構
 * @author zls
 * @date 2019/12/26
 */
public class TreeTest {

    // 定義全局變量,統計地櫃中總的循環次數
    private static int time;

    /**
     * 初始化數據,模擬從數據查詢出來的數據
     * @return
     */
    public static List<Menu> initData() {
        List<Menu> menus = new ArrayList<>();

        menus.add(new Menu("0", "xxx公司", "", "1"));
        menus.add(new Menu("1", "財務部", "0", "2"));
        menus.add(new Menu("2", "人事部", "0", "2"));
        menus.add(new Menu("11", "財務部11", "1", "3"));
        menus.add(new Menu("12", "財務部12", "1", "3"));
        menus.add(new Menu("22", "財務部22", "2", "3"));
        menus.add(new Menu("21", "財務部21", "2", "3"));

        return menus;
    }

    public static void main(String[] args) {
        getTree();
    }

    /**
     * 構建樹形結構
     */
    public static void getTree() {
        List<Menu> menus = initData();
        long start = System.currentTimeMillis();

        // 方法一
//        Menu root = new Menu();
//        Menu menu = buildNodes(root, menus);
//        System.out.println("JSON.toJSONString(root) = " + JSON.toJSONString(menu)); // 300s左右  遞歸循環了23次

        // 方法二
        Menu root1 = new Menu("0", "xxx公司", "", "1");
        buildNodes1(root1, menus); // 此處假設了根節點,如果再加上你去找根節點,那么此方法花費的時間可能更多
        System.out.println("JSON.toJSONString(root) = " + JSON.toJSONString(root1)); // 750s左右, 可能更多   遞歸循環了49次
        System.out.println("time = " + time);
        long end = System.currentTimeMillis();
        System.out.println("花費時間 = " + (end-start) +"毫秒");
    }

    /**
     * 方法二:構建子節點
     * @param commonModel
     * @param list
     */
    public static void buildNodes1(Menu commonModel, List<Menu> list) {
        list.forEach(l -> {
            time++;
            if (commonModel.getId().equalsIgnoreCase((String) l.getParentId())) {
                Menu c = new Menu();
                BeanUtils.copyProperties(l, c);
                buildNodes1(c, list);
                commonModel.getNodes().add(c);
            }
        });
    }

    /**
     * 方法一:構建子節點
     * @param root
     * @param nodes
     * @return
     */
    public static Menu buildNodes(Menu root, List<Menu> nodes) {

        // 剩余節點(還沒有找到父節點的節點)
        ArrayList<Menu> remainNodes = new ArrayList<>();
        // 當前節點下的子節點
        ArrayList<Menu> child = new ArrayList<>();

        Iterator<Menu> iterator = nodes.iterator();
        while (iterator.hasNext()) {
            time++;
            Menu node = iterator.next();
            if (Objects.equals(node.getLevel(), "1")) {
                root = node;
                continue;
            }
            // 該節點找到了子節點
            if (Objects.equals(root.getId(), node.getParentId())) {
                child.add(node);
            } else {
                // 沒有找到子節點
                remainNodes.add(node);
            }
        }
        // 根節點設置子節點
        root.setNodes(child);
        // 每一個節點再去尋找對應的子節點
        root.getNodes().stream().forEach(x -> {
            buildNodes(x, remainNodes);
        });
        return root;
    }
}

/**
 * 樹形菜單
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
class Menu implements Serializable {
    private String id;
    private String name; // 菜單名稱
    private String parentId; // 父id
    private String level; // 層級
    private List<Menu> nodes = new ArrayList<>(); // 子節點


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

}

 

結果展示:

{
    "id":"0",
    "level":"1",
    "name":"xxx公司",
    "nodes":[
        {
            "id":"1",
            "level":"2",
            "name":"財務部",
            "nodes":[
                {
                    "id":"11",
                    "level":"3",
                    "name":"財務部11",
                    "nodes":[

                    ],
                    "parentId":"1"
                },
                {
                    "id":"12",
                    "level":"3",
                    "name":"財務部12",
                    "nodes":[

                    ],
                    "parentId":"1"
                }
            ],
            "parentId":"0"
        },
        {
            "id":"2",
            "level":"2",
            "name":"人事部",
            "nodes":[
                {
                    "id":"22",
                    "level":"3",
                    "name":"財務部22",
                    "nodes":[

                    ],
                    "parentId":"2"
                },
                {
                    "id":"21",
                    "level":"3",
                    "name":"財務部21",
                    "nodes":[

                    ],
                    "parentId":"2"
                }
            ],
            "parentId":"0"
        }
    ],
    "parentId":""
}
View Code

 

如有更優方案,請給出!!!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM