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>

猜你喜欢

转载自zhyp29.iteye.com/blog/2296647
今日推荐