java樹形結構
我們的目標是:完成以下形態的樹狀.
--管理
---高階管理員
----增加
----刪除
----修改
---普通管理員
----增加
一、建表
/**
--樹形選單
節點編號
節點名稱
節點連結址
些節點父節點
是否最底節點
節點排序(一般用在同級節點上)
節點說明
*/
drop table EPTreeTable
create table EPTreeTable
(
TreeNodeId int identity(1,1) constraint pk_TreeNode primary key,
TreeNodeName varchar(50) not null,
TreeNodeLink varchar(100) ,
TreeNodeFatherId int default 0, --0 為最高層
TreeNodeIsBottom bit default 1, --1 為底層 0為非底層
TreeNodeCompositor int default 1, -- 預設排在最後面
TreeNodeExplain varchar(200)
)
二、JAVA程式碼
(1)TO物件
/**
* @author fangbiao
* 用於對映父級選單TO物件
*/
public class ParentResourcePojo {
/**
* 節點編號
*/
private int treeNodeId;
/**
* 節點名稱
*/
private String treeNodeName;
/**
* 父節點
*/
private int treeParentNodeId;
/**
* @return treeNodeName
*/
public String getTreeNodeName() {
return treeNodeName;
}
/**
* @param treeNodeName 要設定的 treeNodeName
*/
public void setTreeNodeName(String treeNodeName) {
this.treeNodeName = treeNodeName;
}
/**
* @return treeParentNodeId
*/
public int getTreeParentNodeId() {
return treeParentNodeId;
}
/**
* @param treeParentNodeId 要設定的 treeParentNodeId
*/
public void setTreeParentNodeId(int treeParentNodeId) {
this.treeParentNodeId = treeParentNodeId;
}
/**
* @return treeNodeId
*/
public int getTreeNodeId() {
return treeNodeId;
}
/**
* @param treeNodeId 要設定的 treeNodeId
*/
public void setTreeNodeId(int treeNodeId) {
this.treeNodeId = treeNodeId;
}
}
(2)樹形組合
/**
* 獲取節點選擇列表資訊
* @return
*/
public List getResourceList(){
if(resourceList.size() == 0) {
//獲取高階的父節點
resourceList = doTurnParentToTree(itbs.getTopParentResource());
}
return resourceList;
}
private int num =2;
private int tempTotalChildren ;
private boolean temp = false;
private int tempParent; //每次遞迴節點的父節點
/**
* 對父級列表進行樹排
* @param prp
* @return
*/
private synchronized List doTurnParentToTree(ParentResourcePojo prp){
if(prp == null)
return null;
List list = getChildrenList(prp);
//分線
tempParent = prp.getTreeParentNodeId();
String str = "";
if(tempParent == 0){
resourceList.add("-"+prp.getTreeNodeName()));
}else{
resourceList.add(prp.getTreeNodeName()));
//每棵樹的節點數目
tempTotalChildren = list.size();
}
Iterator iterator = list.iterator();
while(iterator.hasNext()){
ParentResourcePojo treePojo = (ParentResourcePojo)iterator.next();
if(tempParent != 0){
if( tempParent treePojo.getTreeParentNodeId()){
num -=1;
temp = false;
}else if( tempParent == treePojo.getTreeParentNodeId() ){
if(tempTotalChildren ==0)
temp = false;
else
temp = true;
}
}
for(int i=0;i<num str resourcelist list allparenttreelist="null;" int flag="0;" getallparenttreelist null itbs.getrrcresource prp getchildrenlist listlength="list.size();" newreturnlist="new" arraylist leavelist="new" i="0;i<listLength;i++){" prpojo=" " treepojotreeparantnodeid="prPojo.getTreeParentNodeId();" tptreenodeid="prp.getTreeNodeId();" public class actionbo private string id parentid level menutypeid menutype name url integer sort description commandname date created recordoperationflag userid> actionBOs;
public ActionBO() {
super();
}
public ActionBO(Action action) {
this.id = action.getId();
this.parentId = action.getParentId();
this.name = action.getName();
this.level = action.getLevel();
this.menuTypeId = action.getMenuTypeId();
this.menuType = action.getMenuType();
this.url = action.getUrl();
this.sort = action.getSort();
this.description = action.getDescription();
this.recordOperationFlag = action.getRecordOperationFlag();
this.created = action.getCreated();
this.commandName = action.getCommandName();
}
public ActionBO(String id, String parentId, String level,
String menuTypeId, String menuType, String name, String url,
Integer sort, String description, String commandName, Date created,
String recordOperationFlag, String userId, List<actionbo> actionBOs) {
super();
this.id = id;
this.parentId = parentId;
this.level = level;
this.menuTypeId = menuTypeId;
this.menuType = menuType;
this.name = name;
this.url = url;
this.sort = sort;
this.description = description;
this.commandName = commandName;
this.created = created;
this.recordOperationFlag = recordOperationFlag;
this.userId = userId;
this.actionBOs = actionBOs;
}
}
public class Action {
private String id;
private String parentId;
private String level;
private String menuTypeId;
private String menuType;
private String name;
private String url;
private Integer sort;
private String description;
private String commandName;
private Date created;
private String recordOperationFlag;
public Action() {
super();
}
public Action(String id, String parentId, String level, String menuTypeId,
String menuType, String name, String url, Integer sort,
String description, String commandName, Date created,
String recordOperationFlag) {
super();
this.id = id;
this.parentId = parentId;
this.level = level;
this.menuTypeId = menuTypeId;
this.menuType = menuType;
this.name = name;
this.url = url;
this.sort = sort;
this.description = description;
this.commandName = commandName;
this.created = created;
this.recordOperationFlag = recordOperationFlag;
}
public Action(JSONObject object) {
this.id = object.getString("id");
this.parentId = StringUtils.isEmpty(object.getString("parentId")) ? null : object.getString("parentId");
this.level = object.getString("level");
this.menuTypeId = object.getString("menuTypeId");
this.menuType = object.getString("menuType");
this.name = object.getString("name");
this.url = object.getString("url");
this.sort = object.getInteger("sort");
this.description = object.getString("description");
this.commandName = object.getString("commandName");
this.created = object.getDate("created");
this.recordOperationFlag = object.getString("recordOperationFlag");
}
}
主要方法:
@Override
public List<actionbo> findAll(){
List<actionbo> actionBOs = new ArrayList<actionbo>();
List<action> actions = actionDao.findAll();
for (Action Action : actions) {
if (StringUtils.isEmpty(Action.getParentId())) {
ActionBO actionBO = new ActionBO(Action);
setChildNode(actionBO, actions);
actionBOs.add(actionBO);
}
}
return actionBOs;
}
/**
* 設定樹的子節點
*
* @param actionBO
* @param actions
*/
private void setChildNode(ActionBO actionBO, List<action> actions) {
List<actionbo> actionBOs = new ArrayList<actionbo>();
for (Action Action : actions) {
if (!actionBO.getId().equals(Action.getId())
&& actionBO.getId().equals(Action.getParentId())) {
ActionBO actionBo = new ActionBO(Action);
if (isParent(actions, actionBo)) {
setChildNode(actionBo, actions);
}
actionBOs.add(actionBo);
}
}
actionBO.setActionBOs(actionBOs);
}
/**
* 是否為父節點
*
* @param actions
* @param actionBo
* @return
*/
private boolean isParent(List<action> actions, ActionBO actionBo) {
boolean isParent = false;
for (Action Action : actions) {
if (!actionBo.getId().equals(Action.getId())
&& actionBo.getId().equals(Action.getParentId())) {
isParent = true;
break;
}
}
return isParent;
}
使用遞迴演算法結合資料庫解析成java樹形結構
1、準備表結構及對應的表資料
a、表結構:
create table TB_TREE
(
CID NUMBER not null,
CNAME VARCHAR2(50),
PID NUMBER //父節點
)
b、表資料:
insert into tb_tree (CID, CNAME, PID) values (1, '中國', 0);
insert into tb_tree (CID, CNAME, PID) values (2, '北京市', 1);
insert into tb_tree (CID, CNAME, PID) values (3, '廣東省', 1);
insert into tb_tree (CID, CNAME, PID) values (4, '上海市', 1);
insert into tb_tree (CID, CNAME, PID) values (5, '廣州市', 3);
insert into tb_tree (CID, CNAME, PID) values (6, '深圳市', 3);
insert into tb_tree (CID, CNAME, PID) values (7, '海珠區', 5);
insert into tb_tree (CID, CNAME, PID) values (8, '天河區', 5);
insert into tb_tree (CID, CNAME, PID) values (9, '福田區', 6);
insert into tb_tree (CID, CNAME, PID) values (10, '南山區', 6);
insert into tb_tree (CID, CNAME, PID) values (11, '密雲縣', 2);
insert into tb_tree (CID, CNAME, PID) values (12, '浦東', 4);
2、TreeNode物件,對應tb_tree
public class TreeNode implements Serializable {
private Integer cid;
private String cname;
private Integer pid;
private List nodes = new ArrayList();
public TreeNode() {
}
//getter、setter省略
}
3、測試資料
public class TreeNodeTest {
@Test
public void loadTree() throws Exception{
System.out.println(JsonUtils.javaToJson(recursiveTree(1)));
}
/**
* 遞迴演算法解析成樹形結構
*
* @param cid
* @return
* @author jiqinlin
*/
public TreeNode recursiveTree(int cid) {
//根據cid獲取節點物件(SELECT * FROM tb_tree t WHERE t.cid=?)
TreeNode node = personService.getreeNode(cid);
//查詢cid下的所有子節點(SELECT * FROM tb_tree t WHERE t.pid=?)
List childTreeNodes = personService.queryTreeNode(cid);
//遍歷子節點
for(TreeNode child : childTreeNodes){
TreeNode n = recursiveTree(child.getCid()); //遞迴
node.getNodes().add(n);
}
return node;
}
}
輸出的json格式如下:
{
"cid": 1,
"nodes": [
{
"cid": 2,
"nodes": [
{
"cid": 11,
"nodes": [
],
"cname": "密雲縣",
"pid": 2
}
],
"cname": "北京市",
"pid": 1
},
{
"cid": 3,
"nodes": [
{
"cid": 5,
"nodes": [
{
"cid": 7,
"nodes": [
],
"cname": "海珠區",
"pid": 5
},
{
"cid": 8,
"nodes": [
],
"cname": "天河區",
"pid": 5
}
],
"cname": "廣州市",
"pid": 3
},
{
"cid": 6,
"nodes": [
{
"cid": 9,
"nodes": [
],
"cname": "福田區",
"pid": 6
},
{
"cid": 10,
"nodes": [
],
"cname": "南山區",
"pid": 6
}
],
"cname": "深圳市",
"pid": 3
}
],
"cname": "廣東省",
"pid": 1
},
{
"cid": 4,
"nodes": [
{
"cid": 12,
"nodes": [
],
"cname": "浦東",
"pid": 4
}
],
"cname": "上海市",
"pid": 1
}
],
"cname": "中國",
"pid": 0
}
樹節點類:
package cn.com.tree;
public class Node {
private Integer id;
private Integer parentId;
private String name;
private String link;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Integer getParentId() {
return parentId;
}
public void setParentId(Integer parentId) {
this.parentId = parentId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getLink() {
return link;
}
public void setLink(String link) {
this.link = link;
}
}
輸出樹形選單類:
package cn.com.tree;
import java.util.ArrayList;
import java.util.List;
public class Tree {
private StringBuffer html = new StringBuffer();
private List<node> nodes;
public Tree(List<node> nodes){
this.nodes = nodes;
}
public String buildTree(){
html.append("<ul>");
for (Node node : nodes) {
Integer id = node.getId();
if (node.getParentId() == null) {
html.append("\r\n<li id='" + id + "'>" + node.getName()+ "</li>");
build(node);
}
}
html.append("\r\n</ul>");
return html.toString();
}
private void build(Node node){
List<node> children = getChildren(node);
if (!children.isEmpty()) {
html.append("\r\n<ul>");
for (Node child : children) {
Integer id = child.getId();
html.append("\r\n<li id='" + id + "'>" + child.getName()+ "</li>");
build(child);
}
html.append("\r\n</ul>");
}
}
private List<node> getChildren(Node node){
List<node> children = new ArrayList<node>();
Integer id = node.getId();
for (Node child : nodes) {
if (id.equals(child.getParentId())) {
children.add(child);
}
}
return children;
}
}
測試類:
package zzj.test;
import java.util.ArrayList;
import java.util.List;
import cn.com.tree.Node;
import cn.com.tree.Tree;
public class Test {
/**
* @param args
*/
public static void main(String[] args) {
List<node> nodes = new ArrayList<node>();
Node node1 = new Node();
node1.setId(1);
node1.setName("node1");
node1.setParentId(null);
node1.setLink(null);
nodes.add(node1);
Node node11 = new Node();
node11.setId(11);
node11.setName("node11");
node11.setParentId(1);
node11.setLink(null);
nodes.add(node11);
Node node111 = new Node();
node111.setId(111);
node111.setName("node111");
node111.setParentId(11);
node111.setLink(null);
nodes.add(node111);
Node node12 = new Node();
node12.setId(12);
node12.setName("node12");
node12.setParentId(1);
node12.setLink(null);
nodes.add(node12);
Node node2 = new Node();
node2.setId(2);
node2.setName("node2");
node2.setParentId(null);
node2.setLink(null);
nodes.add(node2);
Node node21 = new Node();
node21.setId(21);
node21.setName("node21");
node21.setParentId(2);
node21.setLink(null);
nodes.add(node21);
Node node3 = new Node();
node3.setId(3);
node3.setName("node3");
node3.setParentId(null);
node3.setLink(null);
nodes.add(node3);
Tree tree = new Tree(nodes);
System.out.println(tree.buildTree());
}
}
輸出:
<ul>
<li id="1">node1</li>
<ul>
<li id="11">node11</li>
<ul>
<li id="111">node111</li>
</ul>
<li id="12">node12</li>
</ul>
<li id="2">node2</li>
<ul>
<li id="21">node21</li>
</ul>
<li id="3">node3</li>
</ul>
三、原始碼實現(Java語言版)
實現這樣一顆樹,需要設計三個類:樹類(MultipleTree.java)、節點類(Node.java)、孩子列表類(Children.java);為了方便演示,還需要構造一些假的層次資料,因此還需要建一個構造假資料的類(VirtualDataGenerator.java),以下程式碼拷貝出來之後可直接執行測試:
Java程式碼
package test;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Collections;
/**
* 多叉樹類
*/
public class MultipleTree {
public static void main(String[] args) {
// 讀取層次資料結果集列表
List dataList = VirtualDataGenerator.getVirtualResult();
// 節點列表(雜湊表,用於臨時儲存節點物件)
HashMap nodeList = new HashMap();
// 根節點
Node root = null;
// 根據結果集構造節點列表(存入雜湊表)
for (Iterator it = dataList.iterator(); it.hasNext();) {
Map dataRecord = (Map) it.next();
Node node = new Node();
node.id = (String) dataRecord.get("id");
node.text = (String) dataRecord.get("text");
node.parentId = (String) dataRecord.get("parentId");
nodeList.put(node.id, node);
}
// 構造無序的多叉樹
Set entrySet = nodeList.entrySet();
for (Iterator it = entrySet.iterator(); it.hasNext();) {
Node node = (Node) ((Map.Entry) it.next()).getValue();
if (node.parentId == null || node.parentId.equals("")) {
root = node;
} else {
((Node) nodeList.get(node.parentId)).addChild(node);
}
}
// 輸出無序的樹形選單的JSON字串
System.out.println(root.toString());
// 對多叉樹進行橫向排序
root.sortChildren();
// 輸出有序的樹形選單的JSON字串
System.out.println(root.toString());
// 程式輸出結果如下(無序的樹形選單)(格式化後的結果):
// {
// id : '100000',
// text : '廊坊銀行總行',
// children : [
// {
// id : '110000',
// text : '廊坊分行',
// children : [
// {
// id : '113000',
// text : '廊坊銀行開發區支行',
// leaf : true
// },
// {
// id : '111000',
// text : '廊坊銀行金光道支行',
// leaf : true
// },
// {
// id : '112000',
// text : '廊坊銀行解放道支行',
// children : [
// {
// id : '112200',
// text : '廊坊銀行三大街支行',
// leaf : true
// },
// {
// id : '112100',
// text : '廊坊銀行廣陽道支行',
// leaf : true
// }
// ]
// }
// ]
// }
// ]
// }
// 程式輸出結果如下(有序的樹形選單)(格式化後的結果):
// {
// id : '100000',
// text : '廊坊銀行總行',
// children : [
// {
// id : '110000',
// text : '廊坊分行',
// children : [
// {
// id : '111000',
// text : '廊坊銀行金光道支行',
// leaf : true
// },
// {
// id : '112000',
// text : '廊坊銀行解放道支行',
// children : [
// {
// id : '112100',
// text : '廊坊銀行廣陽道支行',
// leaf : true
// },
// {
// id : '112200',
// text : '廊坊銀行三大街支行',
// leaf : true
// }
// ]
// },
// {
// id : '113000',
// text : '廊坊銀行開發區支行',
// leaf : true
// }
// ]
// }
// ]
// }
}
}
/**
* 節點類
*/
class Node {
/**
* 節點編號
*/
public String id;
/**
* 節點內容
*/
public String text;
/**
* 父節點編號
*/
public String parentId;
/**
* 孩子節點列表
*/
private Children children = new Children();
// 先序遍歷,拼接JSON字串
public String toString() {
String result = "{"
+ "id : '" + id + "'"
+ ", text : '" + text + "'";
if (children != null && children.getSize() != 0) {
result += ", children : " + children.toString();
} else {
result += ", leaf : true";
}
return result + "}";
}
// 兄弟節點橫向排序
public void sortChildren() {
if (children != null && children.getSize() != 0) {
children.sortChildren();
}
}
// 新增孩子節點
public void addChild(Node node) {
this.children.addChild(node);
}
}
/**
* 孩子列表類
*/
class Children {
private List list = new ArrayList();
public int getSize() {
return list.size();
}
public void addChild(Node node) {
list.add(node);
}
// 拼接孩子節點的JSON字串
public String toString() {
String result = "[";
for (Iterator it = list.iterator(); it.hasNext();) {
result += ((Node) it.next()).toString();
result += ",";
}
result = result.substring(0, result.length() - 1);
result += "]";
return result;
}
// 孩子節點排序
public void sortChildren() {
// 對本層節點進行排序
// 可根據不同的排序屬性,傳入不同的比較器,這裡傳入ID比較器
Collections.sort(list, new NodeIDComparator());
// 對每個節點的下一層節點進行排序
for (Iterator it = list.iterator(); it.hasNext();) {
((Node) it.next()).sortChildren();
}
}
}
/**
* 節點比較器
*/
class NodeIDComparator implements Comparator {
// 按照節點編號比較
public int compare(Object o1, Object o2) {
int j1 = Integer.parseInt(((Node)o1).id);
int j2 = Integer.parseInt(((Node)o2).id);
return (j1
<menugroup>
<menu>
</menu>
<menu>
</menu>
<menugroup>
<menu>
</menu>
<menu>
</menu>
</menugroup>
</menugroup>
(2)UL - LI 層次結構
Html程式碼
<ul>
<li>廊坊銀行總行</li>
<ul>
<li>廊坊分行</li>
<ul>
<li>廊坊銀行開發區支行</li>
<li>廊坊銀行解放道支行</li>
<ul>
<li>廊坊銀行三大街支行</li>
<li>廊坊銀行廣陽道支行</li>
</ul>
<li>廊坊銀行金光道支行</li>
</ul>
</ul>
</ul>
(3)TABLE層次結構
Html程式碼
<table>
<tr><td>廊坊銀行總行</td></tr>
<tr><td> 廊坊分行</td></tr>
<tr><td> 廊坊銀行開發區支行</td></tr>
<tr><td> 廊坊銀行解放道支行</td></tr>
<tr><td> 廊坊銀行三大街支行</td></tr>
<tr><td> 廊坊銀行廣陽道支行</td></tr>
<tr><td> 廊坊銀行金光道支行</td></tr>
</table>
另外對TreeGrid樹形表格也有一定的價值:
1、 一次性構造樹形表格,實現資料分級展示
2、 通過更換比較器,實現對不同表格列的全排序(全排序指的是對所有頁的資料進行排序,而不是隻對當前頁的資料排序)
3、 實現對樹形表格的完整分頁(每次分頁時,只取固定數目的第一層節點,之後呼叫toString方法,展示出完 整條數的分級資料)
</node></node></node></node></node></node></node></node></action></actionbo></actionbo></action></action></actionbo></actionbo></actionbo></actionbo></num>
--管理
---高階管理員
----增加
----刪除
----修改
---普通管理員
----增加
一、建表
/**
--樹形選單
節點編號
節點名稱
節點連結址
些節點父節點
是否最底節點
節點排序(一般用在同級節點上)
節點說明
*/
drop table EPTreeTable
create table EPTreeTable
(
TreeNodeId int identity(1,1) constraint pk_TreeNode primary key,
TreeNodeName varchar(50) not null,
TreeNodeLink varchar(100) ,
TreeNodeFatherId int default 0, --0 為最高層
TreeNodeIsBottom bit default 1, --1 為底層 0為非底層
TreeNodeCompositor int default 1, -- 預設排在最後面
TreeNodeExplain varchar(200)
)
二、JAVA程式碼
(1)TO物件
/**
* @author fangbiao
* 用於對映父級選單TO物件
*/
public class ParentResourcePojo {
/**
* 節點編號
*/
private int treeNodeId;
/**
* 節點名稱
*/
private String treeNodeName;
/**
* 父節點
*/
private int treeParentNodeId;
/**
* @return treeNodeName
*/
public String getTreeNodeName() {
return treeNodeName;
}
/**
* @param treeNodeName 要設定的 treeNodeName
*/
public void setTreeNodeName(String treeNodeName) {
this.treeNodeName = treeNodeName;
}
/**
* @return treeParentNodeId
*/
public int getTreeParentNodeId() {
return treeParentNodeId;
}
/**
* @param treeParentNodeId 要設定的 treeParentNodeId
*/
public void setTreeParentNodeId(int treeParentNodeId) {
this.treeParentNodeId = treeParentNodeId;
}
/**
* @return treeNodeId
*/
public int getTreeNodeId() {
return treeNodeId;
}
/**
* @param treeNodeId 要設定的 treeNodeId
*/
public void setTreeNodeId(int treeNodeId) {
this.treeNodeId = treeNodeId;
}
}
(2)樹形組合
/**
* 獲取節點選擇列表資訊
* @return
*/
public List getResourceList(){
if(resourceList.size() == 0) {
//獲取高階的父節點
resourceList = doTurnParentToTree(itbs.getTopParentResource());
}
return resourceList;
}
private int num =2;
private int tempTotalChildren ;
private boolean temp = false;
private int tempParent; //每次遞迴節點的父節點
/**
* 對父級列表進行樹排
* @param prp
* @return
*/
private synchronized List doTurnParentToTree(ParentResourcePojo prp){
if(prp == null)
return null;
List list = getChildrenList(prp);
//分線
tempParent = prp.getTreeParentNodeId();
String str = "";
if(tempParent == 0){
resourceList.add("-"+prp.getTreeNodeName()));
}else{
resourceList.add(prp.getTreeNodeName()));
//每棵樹的節點數目
tempTotalChildren = list.size();
}
Iterator iterator = list.iterator();
while(iterator.hasNext()){
ParentResourcePojo treePojo = (ParentResourcePojo)iterator.next();
if(tempParent != 0){
if( tempParent treePojo.getTreeParentNodeId()){
num -=1;
temp = false;
}else if( tempParent == treePojo.getTreeParentNodeId() ){
if(tempTotalChildren ==0)
temp = false;
else
temp = true;
}
}
for(int i=0;i<num str resourcelist list allparenttreelist="null;" int flag="0;" getallparenttreelist null itbs.getrrcresource prp getchildrenlist listlength="list.size();" newreturnlist="new" arraylist leavelist="new" i="0;i<listLength;i++){" prpojo=" " treepojotreeparantnodeid="prPojo.getTreeParentNodeId();" tptreenodeid="prp.getTreeNodeId();" public class actionbo private string id parentid level menutypeid menutype name url integer sort description commandname date created recordoperationflag userid> actionBOs;
public ActionBO() {
super();
}
public ActionBO(Action action) {
this.id = action.getId();
this.parentId = action.getParentId();
this.name = action.getName();
this.level = action.getLevel();
this.menuTypeId = action.getMenuTypeId();
this.menuType = action.getMenuType();
this.url = action.getUrl();
this.sort = action.getSort();
this.description = action.getDescription();
this.recordOperationFlag = action.getRecordOperationFlag();
this.created = action.getCreated();
this.commandName = action.getCommandName();
}
public ActionBO(String id, String parentId, String level,
String menuTypeId, String menuType, String name, String url,
Integer sort, String description, String commandName, Date created,
String recordOperationFlag, String userId, List<actionbo> actionBOs) {
super();
this.id = id;
this.parentId = parentId;
this.level = level;
this.menuTypeId = menuTypeId;
this.menuType = menuType;
this.name = name;
this.url = url;
this.sort = sort;
this.description = description;
this.commandName = commandName;
this.created = created;
this.recordOperationFlag = recordOperationFlag;
this.userId = userId;
this.actionBOs = actionBOs;
}
}
public class Action {
private String id;
private String parentId;
private String level;
private String menuTypeId;
private String menuType;
private String name;
private String url;
private Integer sort;
private String description;
private String commandName;
private Date created;
private String recordOperationFlag;
public Action() {
super();
}
public Action(String id, String parentId, String level, String menuTypeId,
String menuType, String name, String url, Integer sort,
String description, String commandName, Date created,
String recordOperationFlag) {
super();
this.id = id;
this.parentId = parentId;
this.level = level;
this.menuTypeId = menuTypeId;
this.menuType = menuType;
this.name = name;
this.url = url;
this.sort = sort;
this.description = description;
this.commandName = commandName;
this.created = created;
this.recordOperationFlag = recordOperationFlag;
}
public Action(JSONObject object) {
this.id = object.getString("id");
this.parentId = StringUtils.isEmpty(object.getString("parentId")) ? null : object.getString("parentId");
this.level = object.getString("level");
this.menuTypeId = object.getString("menuTypeId");
this.menuType = object.getString("menuType");
this.name = object.getString("name");
this.url = object.getString("url");
this.sort = object.getInteger("sort");
this.description = object.getString("description");
this.commandName = object.getString("commandName");
this.created = object.getDate("created");
this.recordOperationFlag = object.getString("recordOperationFlag");
}
}
主要方法:
@Override
public List<actionbo> findAll(){
List<actionbo> actionBOs = new ArrayList<actionbo>();
List<action> actions = actionDao.findAll();
for (Action Action : actions) {
if (StringUtils.isEmpty(Action.getParentId())) {
ActionBO actionBO = new ActionBO(Action);
setChildNode(actionBO, actions);
actionBOs.add(actionBO);
}
}
return actionBOs;
}
/**
* 設定樹的子節點
*
* @param actionBO
* @param actions
*/
private void setChildNode(ActionBO actionBO, List<action> actions) {
List<actionbo> actionBOs = new ArrayList<actionbo>();
for (Action Action : actions) {
if (!actionBO.getId().equals(Action.getId())
&& actionBO.getId().equals(Action.getParentId())) {
ActionBO actionBo = new ActionBO(Action);
if (isParent(actions, actionBo)) {
setChildNode(actionBo, actions);
}
actionBOs.add(actionBo);
}
}
actionBO.setActionBOs(actionBOs);
}
/**
* 是否為父節點
*
* @param actions
* @param actionBo
* @return
*/
private boolean isParent(List<action> actions, ActionBO actionBo) {
boolean isParent = false;
for (Action Action : actions) {
if (!actionBo.getId().equals(Action.getId())
&& actionBo.getId().equals(Action.getParentId())) {
isParent = true;
break;
}
}
return isParent;
}
使用遞迴演算法結合資料庫解析成java樹形結構
1、準備表結構及對應的表資料
a、表結構:
create table TB_TREE
(
CID NUMBER not null,
CNAME VARCHAR2(50),
PID NUMBER //父節點
)
b、表資料:
insert into tb_tree (CID, CNAME, PID) values (1, '中國', 0);
insert into tb_tree (CID, CNAME, PID) values (2, '北京市', 1);
insert into tb_tree (CID, CNAME, PID) values (3, '廣東省', 1);
insert into tb_tree (CID, CNAME, PID) values (4, '上海市', 1);
insert into tb_tree (CID, CNAME, PID) values (5, '廣州市', 3);
insert into tb_tree (CID, CNAME, PID) values (6, '深圳市', 3);
insert into tb_tree (CID, CNAME, PID) values (7, '海珠區', 5);
insert into tb_tree (CID, CNAME, PID) values (8, '天河區', 5);
insert into tb_tree (CID, CNAME, PID) values (9, '福田區', 6);
insert into tb_tree (CID, CNAME, PID) values (10, '南山區', 6);
insert into tb_tree (CID, CNAME, PID) values (11, '密雲縣', 2);
insert into tb_tree (CID, CNAME, PID) values (12, '浦東', 4);
2、TreeNode物件,對應tb_tree
public class TreeNode implements Serializable {
private Integer cid;
private String cname;
private Integer pid;
private List nodes = new ArrayList();
public TreeNode() {
}
//getter、setter省略
}
3、測試資料
public class TreeNodeTest {
@Test
public void loadTree() throws Exception{
System.out.println(JsonUtils.javaToJson(recursiveTree(1)));
}
/**
* 遞迴演算法解析成樹形結構
*
* @param cid
* @return
* @author jiqinlin
*/
public TreeNode recursiveTree(int cid) {
//根據cid獲取節點物件(SELECT * FROM tb_tree t WHERE t.cid=?)
TreeNode node = personService.getreeNode(cid);
//查詢cid下的所有子節點(SELECT * FROM tb_tree t WHERE t.pid=?)
List childTreeNodes = personService.queryTreeNode(cid);
//遍歷子節點
for(TreeNode child : childTreeNodes){
TreeNode n = recursiveTree(child.getCid()); //遞迴
node.getNodes().add(n);
}
return node;
}
}
輸出的json格式如下:
{
"cid": 1,
"nodes": [
{
"cid": 2,
"nodes": [
{
"cid": 11,
"nodes": [
],
"cname": "密雲縣",
"pid": 2
}
],
"cname": "北京市",
"pid": 1
},
{
"cid": 3,
"nodes": [
{
"cid": 5,
"nodes": [
{
"cid": 7,
"nodes": [
],
"cname": "海珠區",
"pid": 5
},
{
"cid": 8,
"nodes": [
],
"cname": "天河區",
"pid": 5
}
],
"cname": "廣州市",
"pid": 3
},
{
"cid": 6,
"nodes": [
{
"cid": 9,
"nodes": [
],
"cname": "福田區",
"pid": 6
},
{
"cid": 10,
"nodes": [
],
"cname": "南山區",
"pid": 6
}
],
"cname": "深圳市",
"pid": 3
}
],
"cname": "廣東省",
"pid": 1
},
{
"cid": 4,
"nodes": [
{
"cid": 12,
"nodes": [
],
"cname": "浦東",
"pid": 4
}
],
"cname": "上海市",
"pid": 1
}
],
"cname": "中國",
"pid": 0
}
樹節點類:
package cn.com.tree;
public class Node {
private Integer id;
private Integer parentId;
private String name;
private String link;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Integer getParentId() {
return parentId;
}
public void setParentId(Integer parentId) {
this.parentId = parentId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getLink() {
return link;
}
public void setLink(String link) {
this.link = link;
}
}
輸出樹形選單類:
package cn.com.tree;
import java.util.ArrayList;
import java.util.List;
public class Tree {
private StringBuffer html = new StringBuffer();
private List<node> nodes;
public Tree(List<node> nodes){
this.nodes = nodes;
}
public String buildTree(){
html.append("<ul>");
for (Node node : nodes) {
Integer id = node.getId();
if (node.getParentId() == null) {
html.append("\r\n<li id='" + id + "'>" + node.getName()+ "</li>");
build(node);
}
}
html.append("\r\n</ul>");
return html.toString();
}
private void build(Node node){
List<node> children = getChildren(node);
if (!children.isEmpty()) {
html.append("\r\n<ul>");
for (Node child : children) {
Integer id = child.getId();
html.append("\r\n<li id='" + id + "'>" + child.getName()+ "</li>");
build(child);
}
html.append("\r\n</ul>");
}
}
private List<node> getChildren(Node node){
List<node> children = new ArrayList<node>();
Integer id = node.getId();
for (Node child : nodes) {
if (id.equals(child.getParentId())) {
children.add(child);
}
}
return children;
}
}
測試類:
package zzj.test;
import java.util.ArrayList;
import java.util.List;
import cn.com.tree.Node;
import cn.com.tree.Tree;
public class Test {
/**
* @param args
*/
public static void main(String[] args) {
List<node> nodes = new ArrayList<node>();
Node node1 = new Node();
node1.setId(1);
node1.setName("node1");
node1.setParentId(null);
node1.setLink(null);
nodes.add(node1);
Node node11 = new Node();
node11.setId(11);
node11.setName("node11");
node11.setParentId(1);
node11.setLink(null);
nodes.add(node11);
Node node111 = new Node();
node111.setId(111);
node111.setName("node111");
node111.setParentId(11);
node111.setLink(null);
nodes.add(node111);
Node node12 = new Node();
node12.setId(12);
node12.setName("node12");
node12.setParentId(1);
node12.setLink(null);
nodes.add(node12);
Node node2 = new Node();
node2.setId(2);
node2.setName("node2");
node2.setParentId(null);
node2.setLink(null);
nodes.add(node2);
Node node21 = new Node();
node21.setId(21);
node21.setName("node21");
node21.setParentId(2);
node21.setLink(null);
nodes.add(node21);
Node node3 = new Node();
node3.setId(3);
node3.setName("node3");
node3.setParentId(null);
node3.setLink(null);
nodes.add(node3);
Tree tree = new Tree(nodes);
System.out.println(tree.buildTree());
}
}
輸出:
<ul>
<li id="1">node1</li>
<ul>
<li id="11">node11</li>
<ul>
<li id="111">node111</li>
</ul>
<li id="12">node12</li>
</ul>
<li id="2">node2</li>
<ul>
<li id="21">node21</li>
</ul>
<li id="3">node3</li>
</ul>
三、原始碼實現(Java語言版)
實現這樣一顆樹,需要設計三個類:樹類(MultipleTree.java)、節點類(Node.java)、孩子列表類(Children.java);為了方便演示,還需要構造一些假的層次資料,因此還需要建一個構造假資料的類(VirtualDataGenerator.java),以下程式碼拷貝出來之後可直接執行測試:
Java程式碼
package test;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Collections;
/**
* 多叉樹類
*/
public class MultipleTree {
public static void main(String[] args) {
// 讀取層次資料結果集列表
List dataList = VirtualDataGenerator.getVirtualResult();
// 節點列表(雜湊表,用於臨時儲存節點物件)
HashMap nodeList = new HashMap();
// 根節點
Node root = null;
// 根據結果集構造節點列表(存入雜湊表)
for (Iterator it = dataList.iterator(); it.hasNext();) {
Map dataRecord = (Map) it.next();
Node node = new Node();
node.id = (String) dataRecord.get("id");
node.text = (String) dataRecord.get("text");
node.parentId = (String) dataRecord.get("parentId");
nodeList.put(node.id, node);
}
// 構造無序的多叉樹
Set entrySet = nodeList.entrySet();
for (Iterator it = entrySet.iterator(); it.hasNext();) {
Node node = (Node) ((Map.Entry) it.next()).getValue();
if (node.parentId == null || node.parentId.equals("")) {
root = node;
} else {
((Node) nodeList.get(node.parentId)).addChild(node);
}
}
// 輸出無序的樹形選單的JSON字串
System.out.println(root.toString());
// 對多叉樹進行橫向排序
root.sortChildren();
// 輸出有序的樹形選單的JSON字串
System.out.println(root.toString());
// 程式輸出結果如下(無序的樹形選單)(格式化後的結果):
// {
// id : '100000',
// text : '廊坊銀行總行',
// children : [
// {
// id : '110000',
// text : '廊坊分行',
// children : [
// {
// id : '113000',
// text : '廊坊銀行開發區支行',
// leaf : true
// },
// {
// id : '111000',
// text : '廊坊銀行金光道支行',
// leaf : true
// },
// {
// id : '112000',
// text : '廊坊銀行解放道支行',
// children : [
// {
// id : '112200',
// text : '廊坊銀行三大街支行',
// leaf : true
// },
// {
// id : '112100',
// text : '廊坊銀行廣陽道支行',
// leaf : true
// }
// ]
// }
// ]
// }
// ]
// }
// 程式輸出結果如下(有序的樹形選單)(格式化後的結果):
// {
// id : '100000',
// text : '廊坊銀行總行',
// children : [
// {
// id : '110000',
// text : '廊坊分行',
// children : [
// {
// id : '111000',
// text : '廊坊銀行金光道支行',
// leaf : true
// },
// {
// id : '112000',
// text : '廊坊銀行解放道支行',
// children : [
// {
// id : '112100',
// text : '廊坊銀行廣陽道支行',
// leaf : true
// },
// {
// id : '112200',
// text : '廊坊銀行三大街支行',
// leaf : true
// }
// ]
// },
// {
// id : '113000',
// text : '廊坊銀行開發區支行',
// leaf : true
// }
// ]
// }
// ]
// }
}
}
/**
* 節點類
*/
class Node {
/**
* 節點編號
*/
public String id;
/**
* 節點內容
*/
public String text;
/**
* 父節點編號
*/
public String parentId;
/**
* 孩子節點列表
*/
private Children children = new Children();
// 先序遍歷,拼接JSON字串
public String toString() {
String result = "{"
+ "id : '" + id + "'"
+ ", text : '" + text + "'";
if (children != null && children.getSize() != 0) {
result += ", children : " + children.toString();
} else {
result += ", leaf : true";
}
return result + "}";
}
// 兄弟節點橫向排序
public void sortChildren() {
if (children != null && children.getSize() != 0) {
children.sortChildren();
}
}
// 新增孩子節點
public void addChild(Node node) {
this.children.addChild(node);
}
}
/**
* 孩子列表類
*/
class Children {
private List list = new ArrayList();
public int getSize() {
return list.size();
}
public void addChild(Node node) {
list.add(node);
}
// 拼接孩子節點的JSON字串
public String toString() {
String result = "[";
for (Iterator it = list.iterator(); it.hasNext();) {
result += ((Node) it.next()).toString();
result += ",";
}
result = result.substring(0, result.length() - 1);
result += "]";
return result;
}
// 孩子節點排序
public void sortChildren() {
// 對本層節點進行排序
// 可根據不同的排序屬性,傳入不同的比較器,這裡傳入ID比較器
Collections.sort(list, new NodeIDComparator());
// 對每個節點的下一層節點進行排序
for (Iterator it = list.iterator(); it.hasNext();) {
((Node) it.next()).sortChildren();
}
}
}
/**
* 節點比較器
*/
class NodeIDComparator implements Comparator {
// 按照節點編號比較
public int compare(Object o1, Object o2) {
int j1 = Integer.parseInt(((Node)o1).id);
int j2 = Integer.parseInt(((Node)o2).id);
return (j1
<menugroup>
<menu>
</menu>
<menu>
</menu>
<menugroup>
<menu>
</menu>
<menu>
</menu>
</menugroup>
</menugroup>
(2)UL - LI 層次結構
Html程式碼
<ul>
<li>廊坊銀行總行</li>
<ul>
<li>廊坊分行</li>
<ul>
<li>廊坊銀行開發區支行</li>
<li>廊坊銀行解放道支行</li>
<ul>
<li>廊坊銀行三大街支行</li>
<li>廊坊銀行廣陽道支行</li>
</ul>
<li>廊坊銀行金光道支行</li>
</ul>
</ul>
</ul>
(3)TABLE層次結構
Html程式碼
<table>
<tr><td>廊坊銀行總行</td></tr>
<tr><td> 廊坊分行</td></tr>
<tr><td> 廊坊銀行開發區支行</td></tr>
<tr><td> 廊坊銀行解放道支行</td></tr>
<tr><td> 廊坊銀行三大街支行</td></tr>
<tr><td> 廊坊銀行廣陽道支行</td></tr>
<tr><td> 廊坊銀行金光道支行</td></tr>
</table>
另外對TreeGrid樹形表格也有一定的價值:
1、 一次性構造樹形表格,實現資料分級展示
2、 通過更換比較器,實現對不同表格列的全排序(全排序指的是對所有頁的資料進行排序,而不是隻對當前頁的資料排序)
3、 實現對樹形表格的完整分頁(每次分頁時,只取固定數目的第一層節點,之後呼叫toString方法,展示出完 整條數的分級資料)
</node></node></node></node></node></node></node></node></action></actionbo></actionbo></action></action></actionbo></actionbo></actionbo></actionbo></num>
相關文章
- 樹形結構
- 樹形結構處理
- JAVA樹形結構 通用程式碼(高效能)Java
- 七、基本資料結構(樹形結構)資料結構
- markdown樹形結構生成工具
- 資料結構中樹形結構簡介資料結構
- LayUI—tree樹形結構的使用UI
- 字串陣列轉為樹形結構字串陣列
- Android 多級樹形結構顯示Android
- Linux 下樹形結構的檢視Linux
- 如何在 Laravel 中去構建部門樹形結構 APILaravelAPI
- 將List物件列表轉為樹形結構物件
- 如何快速、且易懂編寫Java遞迴生成樹形選單結構Java遞迴
- 樹結構與Java實現Java
- iView元件庫之下拉框dropdown(樹形結構)View元件
- Vue遞迴元件實現樹形結構選單Vue遞迴元件
- 聊聊mysql的樹形結構儲存及查詢MySql
- 在vue專案中使用樹形結構的穿梭框Vue
- 值得了解的九種樹形資料結構 - Franco資料結構
- MySQL怎樣透過Adjacency List儲存樹形結構?MySql
- 樹形結構的選單表設計與查詢
- 淺談樹形結構的特性和應用(上):多叉樹,紅黑樹,堆,Trie樹,B樹,B+樹...
- MySql樹形結構(多級選單)查詢設計方案MySql
- Java 樹結構實際應用 四(平衡二叉樹/AVL樹)Java二叉樹
- 樹結構總結
- Java實現遞迴查詢樹結構Java遞迴
- Java資料結構(十五)—— 多路查詢樹Java資料結構
- 前端樹形Tree資料結構使用-🤸🏻♂️各種姿勢總結前端資料結構
- Java將List集合組裝成樹(Tree)樹結構組裝Java
- 樹形資料構造的方法
- JS遞迴過濾樹形結構陣列物件--模糊查詢JS遞迴陣列物件
- Java關於資料結構的實現:樹Java資料結構
- PHP 陣列轉樹結構/樹結構轉陣列PHP陣列
- 樹:基本樹形
- layui.tree樹形結構節點判定條件的刪除操作UI
- 資料結構——樹資料結構
- 資料結構-樹資料結構
- 【Algorithm】樹結構整理Go
- XML 樹結構概述XML