【发布时间】:2016-04-15 09:26:36
【问题描述】:
所以,我有一个由树节点组成的基本树结构,这些树节点链接到具有父和子引用的其他树节点。我想创建一个方法,该方法返回一个从叶节点流向根节点或从根流向叶的 Stream。我已经实现了这一点,但我正在寻找一种创建最少对象的解决方案。最好没有。这是我的代码:
public class TreeNode<TNode> {
private TNode iValue;
private TreeNode<TNode> iParentNode = null;
private List<TreeNode<TNode>> iChildren = new ArrayList<>();
public TreeNode(TNode value) {
this(value, null);
}
private TreeNode(TNode value, TreeNode<TNode> parentNode) {
iValue = value;
iParentNode = parentNode;
}
public Stream<TreeNode<TNode>> streamFromLeaf() {
return StreamSupport.stream(Spliterators.spliteratorUnknownSize(new LeafFirstIterator(this), Spliterator.SIZED),
false);
}
public Stream<TreeNode<TNode>> streamFromRoot() {
return StreamSupport.stream(Spliterators.spliteratorUnknownSize(new RootFirstIterator(this), Spliterator.SIZED),
false);
}
public TNode getValue() {
return iValue;
}
public TreeNode<TNode> getParent() {
return iParentNode;
}
public TreeNode<TNode> addChild(TNode childValue) {
TreeNode<TNode> childNode = new TreeNode<TNode>(childValue, iNodeNameFunction, this);
iChildren.add(childNode);
return childNode;
}
public boolean isLeaf() {
return iChildren.size() == 0;
}
public boolean isRoot() {
return iParentNode == null;
}
public List<TreeNode<TNode>> getChildren() {
return iChildren;
}
class LeafFirstIterator implements Iterator<TreeNode<TNode>> {
private TreeNode<TNode> iNextNode;
LeafFirstIterator(TreeNode<TNode> leafNode) {
iNextNode = leafNode;
}
@Override
public boolean hasNext() {
return iNextNode != null;
}
@Override
public TreeNode<TNode> next() {
TreeNode<TNode> current = iNextNode;
iNextNode = current.getParent();
return current;
}
}
class RootFirstIterator implements Iterator<TreeNode<TNode>> {
private List<TreeNode<TNode>> iNodes = new ArrayList<>();
private int iNextIndex;
RootFirstIterator(TreeNode<TNode> leafNode) {
TreeNode<TNode> currentNode = leafNode;
while (currentNode != null) {
iNodes.add(currentNode);
currentNode = currentNode.getParent();
}
iNextIndex = iNodes.size() - 1;
}
@Override
public boolean hasNext() {
return iNextIndex >= 0;
}
@Override
public TreeNode<TNode> next() {
return iNodes.get(iNextIndex--);
}
}
}
这很好用,但我的“问题”是,为每个流调用创建了很多对象。
- StreamSupport.stream 创建新的 ReferencePipeline
- Spliterators.spliteratorUnknownSize 创建新的 IteratorSpliterator
- 我创建了自己的 Iterator 实现以传递给 Spliterator
- RootFirstIterator 创建新的 ArrayList
流将被大量使用,所以我想尽可能避免创建对象。在没有流的情况下迭代树结构是一件简单的事情。现在我只使用stream的map方法。我可以只使用一个接受消费者的方法,迭代深度并为每个节点调用消费者,并且不会创建任何对象,但我会失去所有流功能。看起来像这样:
public void iterateUp(Consumer<TreeNode<TNode>> consumer) {
doIterateUp(this, consumer);
}
public static <T> void doIterateUp(TreeNode<T> node, Consumer<TreeNode<T>> consumer) {
if (node == null)
return;
consumer.accept(node);
doIterateUp(node.getParent(), consumer);
}
从根目录向下迭代同样简单。
对此有什么想法吗?我会以错误的方式解决这个问题吗? TreeNode 应该实现或扩展一些接口/类吗?让我知道是否有任何不清楚的地方。
谢谢!
【问题讨论】:
标签: java tree java-8 java-stream