一个通用的TreeIterator

因工作需要,写了一个通用的树迭代器。主体逻辑参考了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
{}

}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值