因工作需要,写了一个通用的树迭代器。主体逻辑参考了AOM (www.operamasks.org)的ComponentIterator,作了以下改进:
1. 接受任意节点类型(泛型参数)
2. 加入了一个stack来跟踪parent (节点无需提供getParent)
3. 加入了一个函数接口来过滤子树
主类:
public abstract class TreeIterator<Node> implements Iterator<Node>
{
private Node root;
private Node current;
private Node next;
private Fun1<Node, Boolean> subTreeFilter;
private Map<Node, Iterator<Node>> iteratorMap = new IdentityHashMap<Node, Iterator<Node>>();
private Deque<Node> path = new ArrayDeque<Node>();
public TreeIterator(Node root, boolean includeRoot, Fun1<Node, Boolean> subTreeFilter)
{
this.root = root;
this.subTreeFilter = subTreeFilter;
if (includeRoot && isSubTreeAccepted(root))
{
current = next = root;
}
else
{
current = next = getNextNode(root);
}
this.subTreeFilter = subTreeFilter;
}
private boolean isSubTreeAccepted(Node c)
{
if (subTreeFilter != null && !subTreeFilter.apply(c)) return false;
return true;
}
public boolean hasNext()
{
if (next == null && current != null)
{
current = next = getNextNode(current);
}
return next != null;
}
public Node next()
{
if (!hasNext())
{
throw new NoSuchElementException();
}
Node result = next;
next = null;
return result;
}
public void remove()
{
throw new UnsupportedOperationException();
}
private Node getNextNode(Node node)
{
Iterator<Node> children = getChildren(node);
if (children != null)
{
while (children.hasNext())
{
Node next = children.next();
if (isSubTreeAccepted(next))
{
iteratorMap.put(node, children);
path.push(node);
return next;
}
}
}
if (node == root)
{
return null;
}
Node next;
while ((next = getNextSibling(node)) == null)
{
node = path.pop();
if (node == null || node == root) return null;
}
return next;
}
private Node getNextSibling(Node node)
{
Node parent = path.peek();
if (parent == null)
{
return null;
}
Iterator<Node> children = iteratorMap.get(parent);
Node result = null;
if (children != null)
{
while (children.hasNext())
{
Node next = children.next();
if (isSubTreeAccepted(next))
{
result = next;
break;
}
}
}
if (result == null)
{
iteratorMap.remove(parent);
}
return result;
}
protected abstract Iterator<Node> getChildren(Node node);
}
Filter辅助类(用于过滤子树)
public abstract class Fun1<P1, R>
{
protected abstract R f (P1 arg0) throws Exception;
public final R apply(P1 arg0) {
try {
return f(arg0);
} catch(Exception e) {
throw new FunctionException(e);
}
}
}
public class FunctionException extends RuntimeException
{
private static final long serialVersionUID = 1L;
public FunctionException()
{
super();
}
public FunctionException(String message, Throwable cause)
{
super(message, cause);
}
public FunctionException(String message)
{
super(message);
}
public FunctionException(Throwable cause)
{
super(cause);
}
}
UnitTest (用法参考)
public class TreeIteratorTest
{
class TreeNode {
private String value;
private List<TreeNode> children;
public TreeNode(String value, TreeNode... children)
{
super();
this.value = value;
this.children = Arrays.asList(children);
}
public TreeNode(String value)
{
super();
this.value = value;
this.children = null;
}
public String getValue()
{
return value;
}
public void setValue(String value)
{
this.value = value;
}
public List<TreeNode> getChildren()
{
return children;
}
public void setChildren(List<TreeNode> children)
{
this.children = children;
}
@Override
public String toString()
{
return "TreeNode [value=" + value + "]";
}
}
private TreeNode root;
private TreeNode node(String value) {
return new TreeNode(value);
}
private TreeNode node(String value, TreeNode... nodes) {
return new TreeNode(value, nodes);
}
class TreeNodeIterator extends TreeIterator<TreeNode> {
public TreeNodeIterator(TreeNode root, boolean includeRoot, Fun1<TreeNode, Boolean> subTreeFilter)
{
super(root, includeRoot, subTreeFilter);
}
@Override
protected Iterator<TreeNode> getChildren(TreeNode node)
{
return node.getChildren() != null ? node.getChildren().iterator() : null;
}
}
@Before
public void setUp() throws Exception
{
root = node("root",
node("child1",
node ("child11"),
node ("child12")),
node("child2"),
node("child3",
node ("child31"),
node ("child32",
node("child321"),
node("child322")),
node ("child33"))
);
}
@Test
public void testFullScan() throws Exception
{
TreeNodeIterator it = new TreeNodeIterator(root, true, null);
StringBuilder sb = new StringBuilder();
while (it.hasNext()) {
sb.append(it.next().getValue()).append('|');
}
assertEquals("root|child1|child11|child12|child2|child3|child31|child32|child321|child322|child33|", sb.toString());
}
@Test
public void testFullScanWithoutRoot() throws Exception
{
TreeNodeIterator it = new TreeNodeIterator(root, false, null);
StringBuilder sb = new StringBuilder();
while (it.hasNext()) {
sb.append(it.next().getValue()).append('|');
}
assertEquals("child1|child11|child12|child2|child3|child31|child32|child321|child322|child33|", sb.toString());
}
@Test
public void testFullScanWithoutBranch3() throws Exception
{
TreeNodeIterator it = new TreeNodeIterator(root, false, new Fun1<TreeNode, Boolean>() {
@Override protected Boolean f(TreeNode arg0) throws Exception
{
return !arg0.value.equals("child3");
}});
StringBuilder sb = new StringBuilder();
while (it.hasNext()) {
sb.append(it.next().getValue()).append('|');
}
assertEquals("child1|child11|child12|child2|", sb.toString());
}
@Test
public void testFullScanWithoutBranch32() throws Exception
{
TreeNodeIterator it = new TreeNodeIterator(root, false, new Fun1<TreeNode, Boolean>() {
@Override protected Boolean f(TreeNode arg0) throws Exception
{
return !arg0.value.equals("child32");
}});
StringBuilder sb = new StringBuilder();
while (it.hasNext()) {
sb.append(it.next().getValue()).append('|');
}
assertEquals("child1|child11|child12|child2|child3|child31|child33|", sb.toString());
}
@Test
public void testFullScanSingleNode() throws Exception
{
TreeNodeIterator it = new TreeNodeIterator(node("root"), true, null);
StringBuilder sb = new StringBuilder();
while (it.hasNext()) {
sb.append(it.next().getValue()).append('|');
}
assertEquals("root|", sb.toString());
}
@After
public void tearDown() throws Exception
{}
}
分享到:
相关推荐
一个通用的PHP广告(推广投放)竞价页订单管理系统 一个通用的PHP广告(推广投放)竞价页订单管理系统 一个通用的PHP广告(推广投放)竞价页订单管理系统 一个通用的PHP广告(推广投放)竞价页订单管理系统 一个...
基于SpringBoot搭建的一个通用的OA管理系统,以车辆管理为例 基于SpringBoot搭建的一个通用的OA管理系统,以车辆管理为例 基于SpringBoot搭建的一个通用的OA管理系统,以车辆管理为例 基于SpringBoot搭建的一个通用...
Nvme通用驱动 64Nvme通用驱动 64Nvme通用驱动 64Nvme通用驱动 64Nvme通用驱动 64Nvme通用驱动 64Nvme通用驱动 64Nvme通用驱动 64Nvme通用驱动 64Nvme通用驱动 64Nvme通用驱动 64Nvme通用驱动 64Nvme通用驱动 64Nvme...
基于SpringBoot搭建的一个通用的OA管理系统源码.zip基于SpringBoot搭建的一个通用的OA管理系统源码.zip基于SpringBoot搭建的一个通用的OA管理系统源码.zip基于SpringBoot搭建的一个通用的OA管理系统源码.zip基于...
设计一个通用寄存器组,满足以下要求: ①通用寄存器组中有4个16位的寄存器。 ②当复位信号reset=0时,将通用寄存器组中的4个寄存器清零。 ③通用寄存器组中有1个写入端口,当DRWr=1时,在时钟clk的上升沿将数据总线...
然后我就写了一个基于此的通用脱壳机. 目前支持易语言的两种编译方式 独立编译 和非独立编译.自动识别并修复数据. 特别是独立编译支持相对来说有那么一点用处.因为如果你要Patch人家的程序.你当然希望Patch完以后...
基于Python实现的一个通用的二进制数据分析工具源码+文档说明(下载即用).zip分析任意格式的二进制数据,还能同时查看协议文档。 基于Python实现的一个通用的二进制数据分析工具源码+文档说明(下载即用).zip分析...
"子程序1"可能是指一个示例子程序,用于演示如何在易语言中使用通用型。 5. **强制转换**:在处理通用型数据时,由于通用型可以存储任意类型,因此需要进行强制转换来确保数据的安全性和准确性。易语言提供了相应的...
环境:Windows XP ...这里本人翻写一个通用的线程池类,它可以用来作为工具类处理许多多线程问题。代码注释非常详尽,一行注释一行代码。 阅读对象:非常熟悉Java的基本概念,并且熟悉命令行编写代码的人员。
1、基于SpringBoot+FreeMarker+MyBatis+ExtJs实现的一个通用后台管理系统源码(适合快速迭代开发).zip 2、该资源包括项目的全部源码,下载可以直接使用! 3、本项目适合作为计算机、数学、电子信息等专业的课程设计...
一个通用的登录界面源代码加CSS样式,界面简洁易改,适合各种网页网站的登录和注册页面,小白的话强烈推荐。
Nvme通用驱动 32Nvme通用驱动 32Nvme通用驱动 32Nvme通用驱动 32Nvme通用驱动 32Nvme通用驱动 32Nvme通用驱动 32Nvme通用驱动 32Nvme通用驱动 32Nvme通用驱动 32Nvme通用驱动 32Nvme通用驱动 32Nvme通用驱动 32Nvme...
angularjs的一个通用模板,稍微修改一下即可用作你的课程设计什么的
AxureUX WEB端交互原型通用组件模板库 v3 (组件列表) AxureUX WEB端交互原型通用组件模板库 v3 (组件列表) AxureUX WEB端交互原型通用组件模板库 v3 (组件列表) AxureUX WEB端交互原型通用组件模板库 v3 (组件列表) ...
一个通用的动态链接库类,附带范例程序。
2. 用数据库类库 DC.CommonDbLiteLib针对SqlServer,MySQL,SQLite,Oracle,ODBC,OleDb,Firebird,PostgreSql,DB2,Informix,SqlServerCe连接进行了封装,一般情况下只需要调用一个IDatabaseInfo接口即可使用,...
一个网页通用的测试用例,内容详尽,可供参考。
在实际操作中,我们还需要创建一个BaseMapper接口,继承自通用Mapper提供的接口,这样业务层的Dao就可以继承BaseMapper,从而获取到通用的CRUD方法。同时,为了处理更复杂的业务逻辑,我们还可以自定义特定的Mapper...
通用查询,通用修改,通用插入,通用删除,模糊查询存储过程,上一个通用查询存储过程有错勿下,发现不够及时请原谅