私は親と子の参照を持つ他のツリーノードにリンクするツリーノードからなる基本的なツリー構造を持っています。葉ノードからルートノードへ、またはルートから葉へのストリームを返すメソッドを作成したいと思います。私はこれを既に実装していますが、最小限の量のオブジェクトが作成されるソリューションを探しています。好ましくはない。ここに私のコードは次のとおりです。これは正常に動作しますが、私の「問題」は、オブジェクトの多くは、各ストリームのコールのために作成されているツリー構造の深度ストリームを作成
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がSpliterators.spliteratorUnknownSizeが
- 私はSpliterator に渡す私自身のイテレータの実装を作成IteratorSpliterator
- 新しいRootFirstIteratorはストリームがある
新しいのArrayListを作成し、作成する新しいReferencePipeline
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は代わりにインタフェース/クラスを実装または拡張する必要がありますか?不明な点があれば教えてください。
ありがとうございます!
それは必須ではありませんが、本当にいいです。私の他の考えは、フィルター述語、マップ関数、およびコンシューマーを反復メソッドに渡すことでした。部分的なストリームのようなfuncが生成され、オブジェクトが作成されませんでした。しかし、それは私には少し醜いようです。ノードをリストに集めてストリーミングすると、私の解決策に似たオブジェクト作成が賢明だと思います。 –