所以,我有一個基本的樹結構,它由樹節點和父節點和子節點的引用鏈接到其他樹節點組成。我想創建一個方法,它返回一個從葉節點到根節點或從根到葉的流。我已經實現了這一點,但我正在尋找一個解決方案,創建最少量的對象。優選沒有。這裏是我的代碼:在Tree結構上創建深度流
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
- 創建我自己的迭代器實現傳遞給Spliterator
- RootFirstIterator創造了新的ArrayList
流是會被大量使用,所以我想盡可能避免創建對象。迭代沒有流的樹結構是一件簡單的事情。現在我只使用流的映射方法。我只需要一個方法,它需要一個Consumer,迭代深度併爲每個節點調用消費者,並且不會創建對象,但是我會丟失所有流功能。這看起來像這樣:
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應該實現還是擴展一些接口/類?如果有什麼不清楚,請告訴我。
謝謝!
這不是必須的,但會非常好。我的另一個想法是將一個過濾器謂詞,一個map函數和一個消費者傳遞給迭代方法,我會得到部分流類似的func,並且不會創建任何對象。但對我來說似乎有點難看。將節點收集到列表和流式傳輸中,我認爲非常類似的對象創建方式對我的解決方案是明智的,實際上可能會更好一些。 –