ARTS打卡計劃第5周-SHARE-java構建樹形結構

   在項目開發過程當中,咱們常常會遇到樹形數據結構的設計,例如菜單樹,地區樹和類別樹等等。通常而言,咱們須要把數據庫中記錄全取出來,而後構建樹(注意的是,最好是一次性取出來,若是是ajax按需拉數據則不須要)。下面分享了遞歸和非遞歸兩種方式:java

package test.tree;

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

public class Node {

	private String id;
	private String parentId;

	private String value;
	private Node parent;

	private List<Node> children;

	public Node() {
		super();
		this.children = new ArrayList<>();
	}

	public Node(String value, String id, String parentId) {
		this.value = value;
		this.id = id;
		this.parentId = parentId;
		this.children = new ArrayList<>();
	}

	public String getValue() {
		return value;
	}

	public void setValue(String value) {
		this.value = value;
	}

	public String getId() {
		return id;
	}

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

	public String getParentId() {
		return parentId;
	}

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

	public Node getParent() {
		return parent;
	}

	public void setParent(Node parent) {
		this.parent = parent;
	}

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

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

	public void addChild(Node child) {
		if (!this.children.contains(child) && child != null)
			this.children.add(child);
	}

	@Override
	public boolean equals(Object obj) {
		// TODO Auto-generated method stub
		if(obj instanceof Node) {
			if(this.id.equals(((Node) obj).getId())) {
				return true;
			}
		}
		return false;
	}
	@Override
	public String toString() {
		return "Node [id=" + id + ", parentId=" + parentId + ", value=" + value + ", children=" + children + "]";
	}
}

  非遞歸的方式node

package test.tree;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class ListToTreeNoRecurse {

	public static void main(String[] args) throws IOException {
		List<Node> nodes = new ArrayList<>();
		List<String> lines = Files
				.readAllLines(Paths.get("C:\\Users\\95\\Desktop\\leetCode\\src\\test\\tree\\jsontest.txt"));
		nodes.add(new Node("all", "0", null));
		for (String line : lines) {
			String[] values = line.split(",");
			Node node = new Node(values[1].trim(), values[0].trim(), values[3].trim());
			nodes.add(node);
		}

		long start = System.currentTimeMillis();
		createTree(nodes);
		long end = System.currentTimeMillis();
		System.err.println((end - start));

	}

	private static void createTree(List<Node> nodes) {

		Map<String, Node> mapTmp = new HashMap<>();
		// Save all nodes to a map
		for (Node current : nodes) {	
			mapTmp.put(current.getId(), current);
		
		}
		// loop and assign parent/child relationships
		for (Node current : nodes) {
			String parentId = current.getParentId();
			if (parentId != null) {
				Node parent = mapTmp.get(parentId);
				if (parent != null) {
					current.setParent(parent);
					parent.addChild(current);
					mapTmp.put(parentId, parent);
					mapTmp.put(current.getId(), current);
				}
			}

		}

		System.out.println(mapTmp.get("0"));
		
	}
}

  遞歸的方法來ajax

package test.tree;
 
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;

import test.tree.Node;
 

public class TreeBuilder {
 
 
    /**
     * 使用遞歸方法建樹
     * @param Nodes
     * @return
     */
    public static List<Node> buildByRecursive(List<Node> Nodes) {
        List<Node> trees = new ArrayList<Node>();
        for (Node Node : Nodes) {
            if ("0".equals(Node.getParentId())) {
                trees.add(findChildren(Node,Nodes));
            }
        }
        return trees;
    }
 
    /**
     * 遞歸查找子節點
     * @param Nodes
     * @return
     */
    public static Node findChildren(Node Node,List<Node> Nodes) {
        for (Node it : Nodes) {
            if(Node.getId().equals(it.getParentId())) {
                if (Node.getChildren() == null) {
                    Node.setChildren(new ArrayList<Node>());
                }
                Node.getChildren().add(findChildren(it,Nodes));
            }
        }
        return Node;
    }
 
 
 
    public static void main(String[] args) throws IOException {
    	 List<Node> list = new ArrayList<Node>();
    	 List<String> lines =  Files.readAllLines(Paths.get("C:\\Users\\95\\Desktop\\leetCode\\src\\test\\tree\\jsontest.txt"));
    	for(String line:lines) {
    		String[] values = line.split(",");
    		Node node = new Node(values[1], values[0], values[3]);		
    		list.add(node);
    	}
    	
    	long beforeUsedMem=Runtime.getRuntime().totalMemory()-Runtime.getRuntime().freeMemory();
        long start = System.currentTimeMillis();
        List<Node> trees_ = TreeBuilder.buildByRecursive(list);
        long afterUsedMem=Runtime.getRuntime().totalMemory()-Runtime.getRuntime().freeMemory();
        
        long actualMemUsed=afterUsedMem-beforeUsedMem;

        long end = System.currentTimeMillis();
        System.out.println(trees_);
        System.err.println((end - start));
        System.err.println(actualMemUsed);
    }
 
}

  上述方法的測試數據是世界地區數據,下載地址是:https://epubi.oss-cn-shanghai.aliyuncs.com/jsontest.txt數據庫

  通過測試,若是不打印樹的話,非遞歸方法構建樹是很是快的,遠少於遞歸方法。打印樹的話,非遞歸的方法的性能是略微優於遞歸的。json

  由於非遞歸方法構建的時候,只是構建child,parent之間的引用,在真正打印的時候,會調用toString方法對child進行打印,這個時候也是一個遍歷的過程。在項目中仍是推薦使用非遞歸方法,非遞歸方法比較可控。數據結構

  該方法繼承至AbstractCollection中的toString方法。app

  

    public String toString() {
        Iterator<E> it = iterator();
        if (! it.hasNext())
            return "[]";

        StringBuilder sb = new StringBuilder();
        sb.append('[');
        for (;;) {
            E e = it.next();
            sb.append(e == this ? "(this Collection)" : e);
            if (! it.hasNext())
                return sb.append(']').toString();
            sb.append(',').append(' ');
        }
    }
相關文章
相關標籤/搜索