- 浏览: 3640 次
- 性别:
- 来自: 广州
文章分类
最新评论
我们通常会在应用中碰到树形结构的内容,比如 文件夹/文件模型, 部门组织结构,目录树等等,通常在设计模式中叫做 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
相关推荐
- 常见数据结构:数组、链表、栈、队列、树、图等。 - 常见算法:排序(冒泡、选择、插入、快速等)、查找、递归、动态规划等。 9. **分布式** - 分布式ID生成:如Snowflake算法。 - 分布式缓存:Redis的使用和...
通过阅读和学习这个示例,我们可以了解到如何在实际项目中应用缓存AOP以及如何处理树结构路径参数。这种实践对于提升我们的编程技巧和解决问题的能力非常有帮助。 总结来说,"common_加入缓存AOP,树结构路径参数...
以下是基于标题“数据结构与算法-java”及描述中提到的“数据结构与算法分析_Java语言描述高清版(第2版)1.pdf”所涵盖的一些关键知识点: 1. **数据结构**: - **数组**:最基础的数据结构,存储固定大小的同类型...
在Java编程环境中,读取纯真IP地址数据库是一项常见的任务,尤其对于需要进行IP定位或者网络管理的应用来说。纯真IP数据库(通常称为QQWRY或IPSeeker)是一个包含了全球IP地址及其对应地理位置信息的数据库,它由一...
在Java中遍历MySQL数据库中的树形结构是一个复杂但重要的任务,涉及数据库设计、递归算法以及性能优化等多个方面。通过深入理解树形结构的特点,并采用合适的遍历算法和优化策略,可以有效地管理和操作复杂的层级...
Java中的synchronized关键字和java.util.concurrent包提供了线程安全的数据结构和并发工具,可以用来实现乐观锁、悲观锁或读写锁等并发控制策略。此外,内存数据库必须支持ACID(原子性、一致性、隔离性和持久性)...
在Java高级面试中,拼多多作为一家知名的电商平台,对求职者的技能要求往往较高。这份压缩包文件"java面试——上海-拼多多-Java高级.zip"包含了针对Java高级开发人员的面试问题和解答,帮助应聘者准备面试。以下是...
7. **数据结构与算法**:游戏中的碰撞检测、路径规划等需要高效的数据结构(如数组、链表、树等)和算法支持,例如A*寻路算法、四叉树碰撞检测等。 8. **安全性**:网络安全是必须考虑的问题,如防止作弊、保护用户...
- 对于频繁访问的数据结构,考虑使用哈希表或红黑树等高效数据结构。 9. **测试规约**: - 每个类或关键功能模块应编写相应的单元测试。 - 测试用例需覆盖正常情况、边界情况和异常情况。 - 测试代码应与生产...
- 索引可以极大地提升查询性能,Java中的数据库实现可能需要支持B树、哈希索引等数据结构。 - 查询优化是选择最佳执行计划的过程,包括考虑表的连接顺序、是否使用索引等。 4. **事务处理**: - 事务是数据库...
在SR树中,基数树结构用于处理多维数据的分层索引。 4. **SRTree.java和AbstractNode.java**:这两个文件很可能是SR树的核心实现类。`SRTree.java`可能包含了SR树的构造、插入、删除和查询等操作,而`AbstractNode....
在给定的标题“非常实用的树形菜单,有数据库表”和描述“java实现的非常实用的树形菜单,有数据库表”中,我们可以深入探讨几个关键知识点: 1. **树形菜单**:树形菜单是一种层次结构的展示方式,它通过节点和边...
索引是一种特殊的数据结构,它提高了对数据库表中数据的查找速度。通过在列上创建索引,可以加快查询性能,因为数据库系统不再需要全表扫描,而是直接定位到所需的数据行。然而,索引也会占用额外的存储空间,并可能...
在Java大数据开发工程师的面试中,考察的知识点广泛且深入,涵盖Java编程基础、大数据处理框架、分布式系统、数据库管理、算法与数据结构等多个方面。以下是对这些关键领域的详细解读: 1. **Java编程基础**: - *...
在“butte-java-note-编程文档”中,我们可以探索一系列丰富的IT知识点,涵盖了从基础到高级的Java编程、软件设计、系统架构以及大数据处理等多个领域。以下是对这些知识点的详细阐述: 1. **JVM(Java虚拟机)**:...
在Java面试过程中,尤其是针对中级开发者的职位,面试官通常会关注候选人的基础知识、编程能力、框架理解以及项目经验。深圳作为中国的科技中心之一,中国平安作为一家知名的金融技术公司,其对Java开发者的要求自然...
在IT领域,构建树形结构的数据模型是一种...总之,一次集合遍历实现树形结构是Java和Spring Boot开发中处理层级数据的一种有效方法,它既简洁又高效。理解并掌握这种技巧,对提升后端服务的性能和可维护性大有裨益。
此外,它还涵盖了软件设计模式、数据结构与算法、系统架构设计等高级主题,以及在实际开发中常用的Spring框架、中间件技术、大数据处理、数据库管理、Linux操作系统知识和数据服务相关内容。 【描述】的关键词点...
因此,对于Java语言的理解,例如面向对象设计原则、多线程处理、集合框架的深入理解以及异常处理机制,这些都是面试中的常见话题。在百度的面试中,面试官可能会询问关于JVM(Java虚拟机)的工作原理,如内存模型、...
在Java中,Rtree-java库提供了一种实现R树的方法,使得开发者能够方便地在应用程序中管理、存储和查询多维数据。R树的主要优点在于它可以有效地处理高维数据集,降低因维度灾难( Curse of Dimensionality )导致的...