- 浏览: 3548 次
- 性别:
- 来自: 广州
文章分类
最新评论
我们通常会在应用中碰到树形结构的内容,比如 文件夹/文件模型, 部门组织结构,目录树等等,通常在设计模式中叫做 compose 模式。 Catalog (分级目录)
字段名称
字段
类型
备注
目录ID
catalog_id
varchar(36)
pk, not null
目录名称
catalog_name
varchar(50)
not null
父目录ID
parent_id
varchar(36)
fk
创建时间
create_datetime
datetime
not null
目录描述
description
varchar(200)
Tree.java
package
com.humpic.helper.tree;
public
TreeNode getRootNode() { TreeNode.java package
com.humpic.helper
.tree; 然后建立业务 Tree CatalogTree.java
最后,我们只要使用以下的语句就可以了: 1. CatalogTree.getInstance().getTreeNode(...)
在数据库中常常这样表示: 我们以Catalog (分级目录) 为例子
我们考虑在数据库中一次将所有数据读入内存,然后在内存中生成一个Tree,这样可以减少数据库的访问,增加性能,并且只有的数据方式改变的时候,全部重新从数据库中生成Tree,否则一直保持在内存中。
我们使用标准的DAO模式先生成 POJO类(Catalog)和DAO类(CatalogDAO)。
然后我们建立相对通用的 Tree 和 TreeNode 类。
import
java.util.
*
;
import
org.apache.commons.lang.StringUtils;
import
org.apache.commons.logging.Log;
import
org.apache.commons.logging.LogFactory;
public
abstract
class
Tree {
protected
static
Log log
=
LogFactory.getLog(Tree.
class
);
private
Map treeNodeMaps
=
new
Hashtable();
private
TreeNode root;
/**
* root if it's parent is empty
*/
protected
void
reload(List nodes) {
log.info(
"
tree will start reload all data
"
);
synchronized
(
this
) {
//
initialize
treeNodeMaps.clear();
root
=
null
;
List treeNodes
=
new
Vector(nodes.size());
for
(
int
i
=
0
; i
<
nodes.size(); i
++
) {
TreeNode node
=
this
.transform(nodes.get(i));
//
transform
treeNodes.add(node);
node.setTree(
this
);
treeNodeMaps.put(node.getNodeId(), node);
}
for
(
int
i
=
0
; i
<
treeNodes.size(); i
++
) {
TreeNode node
=
(TreeNode) treeNodes.get(i);
String parentId
=
node.getParentId();
if
(this
.
isRootNode(node)) {
if
(root
==
null
) {
root
=
node;
}
else
{
log.error(
"
find more then one root node. ignore.
"
);
}
}
else
{
TreeNode parent
=
(TreeNode) treeNodeMaps.get(parentId);
if
(parent
!=
null
) {
parent.addChild(node);
node.setParent(parent);
}
else
{
log.warn(
"
node [id=
"
+
node.getNodeId()
+
"
]: missing parent node.
"
);
}
}
}
}
if
(root
==
null
) {
log.error(
"
the root node is not be defined
"
);
}
}
protected
boolean isRootNode(TreeNode node
) {
return
StringUtils.isBlank(node.getParentId()
)
;
}
return
root;
}
public
TreeNode getTreeNode(String nodeId) {
return
(TreeNode) treeNodeMaps.get(nodeId);
}
public
void
addTreeNode(TreeNode node) {
synchronized
(
this
) {
treeNodeMaps.put(node.getNodeId(), node);
String parentId
=
node.getParentId();
if
(StringUtils.isNotBlank(parentId)) {
TreeNode parent
=
getTreeNode(parentId);
if
(parent
!=
null
) {
parent.addChild(node);
node.setParent(parent);
}
else
{
log.error(
"
parent cannot be found:
"
+
node.getParentId());
}
}
else
{
if
(root
==
null
) {
root
=
node;
}
else
{
log.error(
"
find more then one root node. ignore.
"
);
}
}
}
}
public
void
deleteTreeNode(String nodeId) {
synchronized
(
this
) {
TreeNode node
=
getTreeNode(nodeId);
if
(node
==
null
)
throw
new
IllegalArgumentException(nodeId
+
"
cannot be found.
"
);
if
(node.getParent()
==
null
) {
root
=
null
;
treeNodeMaps.clear();
log.warn(
"
the root node has been removed.
"
);
}
else
{
node.getParent().getChildren().remove(node);
treeNodeMaps.remove(nodeId);
List children
=
node.getAllChildren();
for
(
int
i
=
0
; i
<
children.size(); i
++
) {
TreeNode n
=
(TreeNode) children.get(i);
treeNodeMaps.remove(n.getNodeId());
}
}
}
}
/**
* <pre>
* Usage: Office ->
*
* public TreeNode transform(Object info) {
* OfficeInfo office_info = (OfficeInfo) info;
* TreeNode node = new TreeNode();
* node.setNodeId(office_info.getOfficeId());
* node.setParentId(office_info.getParentId());
* node.setBindData(office_info);
* return node;
* }
* </pre>
*/
protected
abstract
TreeNode transform(Object info);
}
import
java.util.List;
import
java.util.Vector;
import
org.apache.commons.collections.Predicate;
import
org.apache.commons.lang.ObjectUtils;
public
class
TreeNode {
private
Tree tree;
private
TreeNode parent;
private
List children
=
new
Vector();
private
List childrenGroup
=
new
Vector();
private
String nodeId;
private
String parentId;
private
Object bindData;
public
String getNodeId() {
return
nodeId;
}
public
void
setNodeId(String nodeId) {
this
.nodeId
=
nodeId;
}
public
String getParentId() {
return
parentId;
}
public
void
setParentId(String parentId) {
this
.parentId
=
parentId;
}
public
Object getBindData() {
return
bindData;
}
public
void
setBindData(Object bindData) {
this
.bindData
=
bindData;
}
public
Tree getTree() {
return
tree;
}
public
void
setTree(Tree tree) {
this
.tree
=
tree;
}
public
void
setParent(TreeNode parent) {
this
.parent
=
parent;
}
public
TreeNode getParent() {
return
this
.parent;
}
public
List getChildren() {
return
this
.children;
}
public
void
addChild(TreeNode node) {
children.add(node);
}
/**
* get all children, and chilren's children
*/
public
List getAllChildren() {
if
(
this
.childrenGroup.isEmpty()) {
synchronized
(
this
.tree) {
for
(
int
i
=
0
; i
<
this
.children.size(); i
++
) {
TreeNode node
=
(TreeNode)
this
.children.get(i);
this
.childrenGroup.add(node);
this
.childrenGroup.addAll(node.getAllChildren());
}
}
}
return
this
.childrenGroup;
}
/**
* get all children, and chilren's children
*/
public
List getAllChildren(Predicate predicate) {
List groups
=
new
Vector();
fillAllChildren(groups, predicate);
return
groups;
}
private
void
fillAllChildren(List groups, Predicate predicate) {
for
(
int
i
=
0
; i
<
this
.children.size(); i
++
) {
TreeNode node
=
(TreeNode)
this
.children.get(i);
if
(predicate.evaluate(node)) {
groups.add(node);
node.fillAllChildren(groups, predicate);
}
}
}
/**
* get all parents, and parent's parent
*/
public
List getParents() {
List results =
new
Vector();
TreeNode parent =
this
.
getParent();
while
(parent !=
null
)
{
results.add(parent);
parent = parent.getParent();
}
return
results;
}
/**
* A.isMyParent(B) == B is A' parent ? <br>
* root.isMyParent(null) == true; <br>
* root.isMyParent(*) == false <br>
* *.isMyParent(null) == false
*/
public
boolean
isMyParent(String nodeId) {
TreeNode target
=
tree.getTreeNode(nodeId);
TreeNode parent
=
this
.getParent();
if
(parent
==
null
) {
return
target
==
null
;
}
else
{
return
parent.equals(target);
}
}
/**
* A.isMyAncestor(B) == B is A' ancestor ? <br>
* *.isMyAncestor(null) == true;
*/
public
boolean
isMyAncestor(String nodeId) {
TreeNode target
=
tree.getTreeNode(nodeId);
if
(target
==
null
)
return
true
;
return
target.getAllChildren().contains(
this
);
}
/**
* A.isMyBrother(B) == B is A' brother ? <br>
* *.isMyBrother(null) == false
*/
public
boolean
isMyBrother(String nodeId) {
TreeNode target
=
tree.getTreeNode(nodeId);
if
(target
==
null
)
return
false
;
TreeNode p1
=
this
.getParent();
TreeNode p2
=
target.getParent();
return
ObjectUtils.equals(p1, p2);
}
}
import
java.util.List;
import
org.apache.commons.collections.Predicate;
public
class
CatalogTree
extends
Tree {
private
static
CatalogTree instance
=
null
;
private
CatalogTree() {}
public
static
synchronized
CatalogTree getInstance() {
if
(instance
==
null
) {
instance
=
new
CatalogTree();
instance.reloadCatalogs();
}
return
instance;
}
protected
TreeNode transform(Object info) {
Catalog catalog
=
(Catalog) info;
TreeNode node
=
new
TreeNode();
node.setNodeId(catalog.getCatalogId());
node.setParentId(catalog.getParentId());
node.setBindData(catalog);
return
node;
}
public
void
reloadCatalogs() {
List nodes
=
CatalogDAO.getInstance().findAll();
super
.reload(nodes);
}
public
Catalog getCatalogNode(String catalogId) {
TreeNode node
=
super
.getTreeNode(catalogId);
return
node
==
null
?
null
: (Catalog) node.getBindData();
}
}
2. CatalogTree.getInstance().getCatalogNode(...)
3. CatalogTree.getInstance().getRootNode()
然后通过 TreeNode,就可以得到 parent, parents 和 children, allChildren
相关推荐
Java企业级开发平台源码 权限管理框架源码 开发语言 : JAVA 数据库 : MySQL ...富文本:KindEcitor、数据表格:jqGrid、树结构控件:jQuery zTree 弹出层:Layer、日期控件: LayDate、图表控件:echarts
19.1.4 由Java应用本身提供数据库连接 19.2 配置事务类型 19.3 把SessionFactory与JNDI绑定 19.4 配置日志 19.5 使用XML格式的配置文件 19.6 小结 19.7 思考题 第20章 声明数据库事务 20.1 数据库...
SimpleCache 是一个简单易用的java缓存工具,用来简化缓存代码的编写,让你摆脱单调乏味的重复工作!1. 完全透明的缓存支持,对业务代码零侵入 2. 支持使用Redis和Memcached作为后端缓存。3. 支持缓存数据分区规则的...
为此,数据库平台一般对表空间设计提 出有相应的优化结构,如ORACLE公司的OFA(Optimal flexible Architecture),使用这种结构进行设计会大大简化物理设计中的数据管理。优化自由结 构,简单地讲就是在数据库中可以...
1 Oracle 结构组件 目标 1-2 基本结构概述 1-3 Oracle 服务器 1-4 Oracle 实例 1-5 建立连接和创建会话 1-6 Oracle 数据库 1-7 物理结构 1-8 内存结构 1-9 系统全局区(SGA) 1-10 共享池 1-12 库缓存 1-13 数据字典...
基于JAVA的UDP服务器模型源代码,内含UDP服务器端模型和UDP客户端模型两个小程序,向JAVA初学者演示UDP C/S结构的原理。 简单聊天软件CS模式 2个目标文件 一个简单的CS模式的聊天软件,用socket实现,比较简单。 ...
涉及缓存,数据容量存储结构(B +树),锁,事务,优化器,重做/撤消日志等核心原理。 1.关系数据结构基本定义 添加数据库,表,行,细分等基础定义 2.数据持久化 每一个表存储成为一个物理磁盘文件,通过表数据变多...
SimpleCache 是一个简单易用的java缓存工具,用来简化缓存代码的编写,让你摆脱单调乏味的重复工作!1. 完全透明的缓存支持,对业务代码零侵入 2. 支持使用Redis和Memcached作为后端缓存。3. 支持缓存数据分区规则的...
基于JAVA的UDP服务器模型源代码,内含UDP服务器端模型和UDP客户端模型两个小程序,向JAVA初学者演示UDP C/S结构的原理。 简单聊天软件CS模式 2个目标文件 一个简单的CS模式的聊天软件,用socket实现,比较简单。 ...
SimpleCache 是一个简单易用的java缓存工具,用来简化缓存代码的编写,让你摆脱单调乏味的重复工作!1. 完全透明的缓存支持,对业务代码零侵入 2. 支持使用Redis和Memcached作为后端缓存。3. 支持缓存数据分区规则的...
SimpleCache 是一个简单易用的java缓存工具,用来简化缓存代码的编写,让你摆脱单调乏味的重复工作!1. 完全透明的缓存支持,对业务代码零侵入 2. 支持使用Redis和Memcached作为后端缓存。3. 支持缓存数据分区规则的...
SimpleCache 是一个简单易用的java缓存工具,用来简化缓存代码的编写,让你摆脱单调乏味的重复工作!1. 完全透明的缓存支持,对业务代码零侵入 2. 支持使用Redis和Memcached作为后端缓存。3. 支持缓存数据分区规则的...
SimpleCache 是一个简单易用的java缓存工具,用来简化缓存代码的编写,让你摆脱单调乏味的重复工作!1. 完全透明的缓存支持,对业务代码零侵入 2. 支持使用Redis和Memcached作为后端缓存。3. 支持缓存数据分区规则的...
SimpleCache 是一个简单易用的java缓存工具,用来简化缓存代码的编写,让你摆脱单调乏味的重复工作!1. 完全透明的缓存支持,对业务代码零侵入 2. 支持使用Redis和Memcached作为后端缓存。3. 支持缓存数据分区规则的...
SimpleCache 是一个简单易用的java缓存工具,用来简化缓存代码的编写,让你摆脱单调乏味的重复工作!1. 完全透明的缓存支持,对业务代码零侵入 2. 支持使用Redis和Memcached作为后端缓存。3. 支持缓存数据分区规则的...
SimpleCache 是一个简单易用的java缓存工具,用来简化缓存代码的编写,让你摆脱单调乏味的重复工作!1. 完全透明的缓存支持,对业务代码零侵入 2. 支持使用Redis和Memcached作为后端缓存。3. 支持缓存数据分区规则的...
打造高效代码结构(java性能优化) 新版本通俗易懂_观察者模式递进时讲解 ibatis连接数据库 高并发之单(多)生产者消费者线程 高并发复用数据库链接技术详解之数据库连接池 类加载器的高级特性(自定义类加器实现加密...
4.2结构化程序设计、面向对象程序设计、可视化程序设计 248 4.3系统测试的目的、类型,系统测试方法 248 4.4系统转换基础知识 249 5.系统运行和维护知识 249 5.1系统运行管理基础知识 249 5.2系统维护基础知识 250 ...
SimpleCache 是一个简单易用的java缓存工具,用来简化缓存代码的编写,让你摆脱单调乏味的重复工作!1. 完全透明的缓存支持,对业务代码零侵入 2. 支持使用Redis和Memcached作为后端缓存。3. 支持缓存数据分区规则的...
SimpleCache 是一个简单易用的java缓存工具,用来简化缓存代码的编写,让你摆脱单调乏味的重复工作!1. 完全透明的缓存支持,对业务代码零侵入 2. 支持使用Redis和Memcached作为后端缓存。3. 支持缓存数据分区规则的...