Java中id,pid格式數據轉樹和森林結構工具類實現
樹形結構很多地方都有應用,比如我們在構造網站后臺的授權限樹的時候,再比如我們在設計多級留言的時候、還有分類等等。
有些時候我們的樹形結構并不需要過多設計,這是因為我們的很多時候對這棵樹的要求不高(兩層、三層就行了),這時候我們很容易的會按照層級劃分樹形結構,然后查詢數據庫的時候會一層一層的嵌套查詢。如果層次比較淺這種做法是可取的(或者我們本來就不打算一次將樹加載完全,而是在需要時再加載,那分層級的多次加載也許有用武之地)。但是考慮這種情況:我們的樹比較深,而且要一次加載完全。要是按照一層一層的加載原則,那么光是訪問數據庫的查詢語句就是指數形式的了。性能肯定不好。那么除了一層一層的查詢好有更好的辦法嗎?肯定是有的,多查詢一些資料會發(fā)現這種做法比較常見了:(id,pid),通俗說就是一個節(jié)點只需要記住自己的id和父親的id(根節(jié)點沒有pid可以設置一個特殊值)就可以擁有呈現這棵樹的完整結構全部信息了,仔細想一想自己學過的數據結構,是不是這樣的?好了這樣一來我們在設計數據庫的時候就可以很輕松的設計一棵樹的樹形結構了。那么有個問題,我們在展現出來的時候總不能直接顯示一連串的(id,pid)集合吧。我們要的是樹形結構。這時候我們其實非常想實現的是從(id,pid)到
(id,children【】)的轉化。畢竟我們在展現樹形結構的時候后一種格式更適合頁面的呈現,而前一種比較適合數據的存儲格式。
好了廢話不多說了,下面是代碼示例:
首先是自定義節(jié)點類:
/**
* 節(jié)點類
* @author bearsmall
*
*/
public class TreeNode {
private int id;//主鍵ID
private int pid;//父節(jié)點ID
private Object content;//節(jié)點內容
private List<TreeNode> children = new ArrayList<TreeNode>();//子孫節(jié)點
public TreeNode(int id, Object content) {
this.id = id;
this.content = content;
}
public TreeNode(int id, int pid, Object content) {
this.id = id;
this.pid = pid;
this.content = content;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getPid() {
return pid;
}
public void setPid(int pid) {
this.pid = pid;
}
public Object getContent() {
return content;
}
public void setContent(Object content) {
this.content = content;
}
public List<TreeNode> getChildren() {
return children;
}
public void setChildren(List<TreeNode> children) {
this.children = children;
}
@Override
public String toString() {
return "TreeNode [id=" + id + ", pid=" + pid + ", content=" + content
+ ", children=" + children + "]";
}
}然后是樹節(jié)點管理類:
/**
* 樹節(jié)點管理類
*
* @author bearsmall
*
*/
public class TreeNodeManager {
private List<TreeNode> list;// 樹的所有節(jié)點
public TreeNodeManager(TreeNode[] items) {
list = new ArrayList<TreeNode>();
for (TreeNode treeNode : items) {
list.add(treeNode);
}
}
public TreeNodeManager(List<TreeNode> items) {
list = items;
}
/**
* 根據節(jié)點ID獲取一個節(jié)點
*
* @param id
* 節(jié)點ID
* @return 對應的節(jié)點對象
*/
public TreeNode getTreeNodeAT(int id) {
for (TreeNode treeNode : list) {
if (treeNode.getId() == id)
return treeNode;
}
return null;
}
/**
* 獲取樹的根節(jié)點
*
* @return 一棵樹的根節(jié)點
*/
public TreeNode getRoot() {
for (TreeNode treeNode : list) {
if (treeNode.getPid() == 0)
return treeNode;
}
return null;
}
}最后是樹節(jié)點轉化類:
/**
* 節(jié)點歸并類
* @author bearsmall
*
*/
public class TreeNodeMerger {
/**
* 將節(jié)點數組歸并為一棵樹(填充節(jié)點的children域)
* 時間復雜度為O(n^2)
* @param items 節(jié)點域
* @return
*/
public static TreeNode merge(TreeNode[] items){
TreeNodeManager treeNodeManager = new TreeNodeManager(items);
for (TreeNode treeNode : items) {
if(treeNode.getPid()!=0){
TreeNode t = treeNodeManager.getTreeNodeAT(treeNode.getPid());
t.getChildren().add(treeNode);
}
}
return treeNodeManager.getRoot();
}
/**
* 將節(jié)點數組歸并為一棵樹(填充節(jié)點的children域)
* 時間復雜度為O(n^2)
* @param items 節(jié)點域
* @return
*/
public static TreeNode merge(List<TreeNode> items){
TreeNodeManager treeNodeManager = new TreeNodeManager(items);
for (TreeNode treeNode : items) {
if(treeNode.getPid()!=0){
TreeNode t = treeNodeManager.getTreeNodeAT(treeNode.getPid());
t.getChildren().add(treeNode);
}
}
return treeNodeManager.getRoot();
}
}簡單測試一下:
public class Main {
public static void main(String[] args) {
TreeNode[] treeNodes = new TreeNode[10];
treeNodes[0] = new TreeNode(1, 0, "");
treeNodes[1] = new TreeNode(2, 1, "");
treeNodes[2] = new TreeNode(3, 1, "");
treeNodes[3] = new TreeNode(4, 2, "");
treeNodes[4] = new TreeNode(5, 3, "");
treeNodes[5] = new TreeNode(6, 4, "");
treeNodes[6] = new TreeNode(7, 3, "");
treeNodes[7] = new TreeNode(8, 5, "");
treeNodes[8] = new TreeNode(9, 6, "");
treeNodes[9] = new TreeNode(10, 9, "");
TreeNode treeNode = TreeNodeMerger.merge(treeNodes);
JSONArray jsonArray = JSONArray.fromObject(treeNode);
System.out.println(jsonArray);
}
}輸出結果:
[{
"children" : [{
"children" : [{
"children" : [{
"children" : [{
"children" : [{
"children" : [],
"pid" : 9,
"id" : 10,
"content" : ""
}
],
"pid" : 6,
"id" : 9,
"content" : ""
}
],
"pid" : 4,
"id" : 6,
"content" : ""
}
],
"pid" : 2,
"id" : 4,
"content" : ""
}
],
"pid" : 1,
"id" : 2,
"content" : ""
}, {
"children" : [{
"children" : [{
"children" : [],
"pid" : 5,
"id" : 8,
"content" : ""
}
],
"pid" : 3,
"id" : 5,
"content" : ""
}, {
"children" : [],
"pid" : 3,
"id" : 7,
"content" : ""
}
],
"pid" : 1,
"id" : 3,
"content" : ""
}
],
"pid" : 0,
"id" : 1,
"content" : ""
}
]這種格式是不是更清晰呢?
森林管理類:
/**
* 森林節(jié)點管理類
*
* @author bearsmall
*
*/
public class ForestNodeManager {
private List<TreeNode> list;// 森林的所有節(jié)點
public ForestNodeManager(TreeNode[] items) {
list = new ArrayList<TreeNode>();
for (TreeNode treeNode : items) {
list.add(treeNode);
}
}
public ForestNodeManager(List<TreeNode> items) {
list = items;
}
/**
* 根據節(jié)點ID獲取一個節(jié)點
*
* @param id
* 節(jié)點ID
* @return 對應的節(jié)點對象
*/
public TreeNode getTreeNodeAT(int id) {
for (TreeNode treeNode : list) {
if (treeNode.getId() == id)
return treeNode;
}
return null;
}
/**
* 獲取樹的根節(jié)點【一個森林對應多顆樹】
*
* @return 樹的根節(jié)點集合
*/
public List<TreeNode> getRoot() {
List<TreeNode> roots = new ArrayList<TreeNode>();
for (TreeNode treeNode : list) {
if (treeNode.getPid() == 0)
roots.add(treeNode);
}
return roots;
}
}森林節(jié)點歸并類:
/**
* 節(jié)點歸并類
* @author bearsmall
*
*/
public class ForestNodeMerger {
/**
* 將節(jié)點數組歸并為一個森林(多棵樹)(填充節(jié)點的children域)
* 時間復雜度為O(n^2)
* @param items 節(jié)點域
* @return 多棵樹的根節(jié)點集合
*/
public static List<TreeNode> merge(TreeNode[] items){
ForestNodeManager forestNodeManager = new ForestNodeManager(items);
for (TreeNode treeNode : items) {
if(treeNode.getPid()!=0){
TreeNode t = forestNodeManager.getTreeNodeAT(treeNode.getPid());
t.getChildren().add(treeNode);
}
}
return forestNodeManager.getRoot();
}
/**
* 將節(jié)點數組歸并為一個森林(多棵樹)(填充節(jié)點的children域)
* 時間復雜度為O(n^2)
* @param items 節(jié)點域
* @return 多棵樹的根節(jié)點集合
*/
public static List<TreeNode> merge(List<TreeNode> items){
ForestNodeManager forestNodeManager = new ForestNodeManager(items);
for (TreeNode treeNode : items) {
if(treeNode.getPid()!=0){
TreeNode t = forestNodeManager.getTreeNodeAT(treeNode.getPid());
t.getChildren().add(treeNode);
}
}
return forestNodeManager.getRoot();
}
}測一下:
public class Main2 {
public static void main(String[] args) {
TreeNode[] treeNodes = new TreeNode[10];
treeNodes[0] = new TreeNode(1, 0, "");
treeNodes[1] = new TreeNode(2, 0, "");
treeNodes[2] = new TreeNode(3, 1, "");
treeNodes[3] = new TreeNode(4, 2, "");
treeNodes[4] = new TreeNode(5, 3, "");
treeNodes[5] = new TreeNode(6, 4, "");
treeNodes[6] = new TreeNode(7, 3, "");
treeNodes[7] = new TreeNode(8, 5, "");
treeNodes[8] = new TreeNode(9, 6, "");
treeNodes[9] = new TreeNode(10, 9, "");
List<TreeNode> tns = ForestNodeMerger.merge(treeNodes);
JSONArray jsonArray = JSONArray.fromObject(tns);
System.out.println(jsonArray);
}
}打印輸出:
[{
"children" : [{
"children" : [{
"children" : [{
"children" : [],
"pid" : 5,
"id" : 8,
"content" : ""
}
],
"pid" : 3,
"id" : 5,
"content" : ""
}, {
"children" : [],
"pid" : 3,
"id" : 7,
"content" : ""
}
],
"pid" : 1,
"id" : 3,
"content" : ""
}
],
"pid" : 0,
"id" : 1,
"content" : ""
}, {
"children" : [{
"children" : [{
"children" : [{
"children" : [{
"children" : [],
"pid" : 9,
"id" : 10,
"content" : ""
}
],
"pid" : 6,
"id" : 9,
"content" : ""
}
],
"pid" : 4,
"id" : 6,
"content" : ""
}
],
"pid" : 2,
"id" : 4,
"content" : ""
}
],
"pid" : 0,
"id" : 2,
"content" : ""
}
]到此這篇關于Java中id,pid格式數據轉樹和森林結構工具類實現的文章就介紹到這了,更多相關Java id,pid格式數據轉樹內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
[Spring MVC]-詳解SpringMVC的各種參數綁定方式
本篇文章主要介紹了SpringMVC的各種參數綁定方式 ,具有一定的參考價值,有需要的可以了解一下。2016-12-12
Java OCR tesseract 圖像智能文字字符識別技術實例代碼
這篇文章主要介紹了Java OCR tesseract 圖像智能文字字符識別技術實例代碼,非常具有實用價值,需要的朋友可以參考下2017-06-06
WIN7系統(tǒng)JavaEE(java)環(huán)境配置教程(一)
這篇文章主要介紹了WIN7系統(tǒng)JavaEE(java+tomcat7+Eclipse)環(huán)境配置教程,本文重點在于java配置,感興趣的小伙伴們可以參考一下2016-06-06

