考虑我想使用Stream API遍历树状结构的一些节点(类似的问题:[1],[2],[3])。首先想到的是:
abstract class Node {
abstract Collection<Node> getChildren();
final Stream<Node> stream() {
return Stream.concat(Stream.of(this), this.getChildren().stream().flatMap(Node::stream));
}
}
上面的stream()
实现具有以下特性:
现在考虑我有一个大的层次结构,<代码> GeHeaveNe()/Cux>操作非常昂贵,我正在寻找任何<代码>节点< /C> >匹配一些谓词:
final Node tree = ...;
final Predicate<Node> p = ...;
tree.stream().filter(p).findAny();
stream()
实现“完全懒惰”?如果节点本身已经匹配谓词,我不希望查询节点的子节点。我正在寻找流的惰性版本。concat()
,签名为(流
有点丑,但这应该适用于Java8:
public static <N> Stream<N> breadthFirst(N start, Function<? super N, Stream<N>> getChildren) {
final LinkedList<Stream<N>> generations = new LinkedList<>();
generations.add(Stream.of(start));
final Iterator<Stream<N>> genIterator = createIterator(generations::remove, () -> !generations.isEmpty());
return StreamSupport.stream(Spliterators.spliteratorUnknownSize(genIterator, Spliterator.ORDERED), false)
.flatMap(Function.identity())
.distinct() // avoids loops
.peek(n -> generations.add(getChildren.apply(n)));
}
public static <E> Iterator<E> createIterator(Supplier<E> supplier, BooleanSupplier hasNext) {
return new Iterator<E>() {
@Override
public boolean hasNext() {
return hasNext.getAsBoolean();
}
@Override
public E next() {
return supplier.get();
}
};
}
这里的想法是,您需要保留对后续代的引用,因此我们创建一个列表以在处理时保存它们。使用Java9,您将能够用流替换自定义迭代器代码。生成(generations::poll)。takeWhile(Objects::nonNull)
。
您可以使用拆分器
库和低级流支持原语。然后,您可以在节点上提供一个迭代器
,该迭代器只逐个使用节点。
return StreamSupport.stream( Spliterators.spliteratorUnknownSize( new Iterator<Node>()
{
@Override
public boolean hasNext()
{
// to implement
return ...;
}
@Override
public ContentVersion next()
{
// to implement
return ...;
}
}, 0 ), false );
不幸的是,我只能回答你的第一个问题。同样,flatMap
是您在这里的朋友。它使我们能够创建一个稍微不同的concat
方法,该方法接受stream-供应商
s,而不仅仅是streams:
abstract class Node {
abstract Collection<Node> getChildren();
Stream<Node> lazyTraverse() {
return Node.concat(() -> Stream.of(this),
() -> getChildren().stream().flatMap(Node::lazyTraverse));
}
static Stream<Node> concat(Supplier<Stream<Node>> a, Supplier<Stream<Node>> b) {
return Stream.of(a, b).flatMap(Supplier::get);
}
}
一个更好的解决方案是,如果您可以用某种返回惰性流的机制替换
getChildren
关于你的第二个问题:
我不知道是否有BFS遍历算法以优雅的方式使用流API,但我倾向于说“不”,因为BFS通常需要额外的内存来存储所有已经访问但尚未遍历的节点。
我正在写一篇关于Java流API的文章。我已经阅读了Stream的整个软件包文档,并在这里查看了类似的问题。 如果我说:“直到终端操作被命中,才会评估流上的中间操作,这将实际执行它们,”我是否正确?我在StackOverflow上看到了混合答案,而且每个中间操作都返回一个Stream,所以我想知道它是否只是返回自己,然后只是跟踪要执行的中间操作。这就是“懒惰评估/执行”的意思吗? 下面的javad
我在研究广度优先搜索或BFS算法时,突然想到了一个主意。我展示了我实现了BFS的图的树形结构。现在也许我可以用链表以不同的方式显示树结构,但是我想修改我用来显示树结构的BFS方法 上面给出的是我的BFS方法,有人可以帮助我让我知道我必须对代码进行哪些确切的修改,以便我获得所需的输出 例如,假设给定的邻接矩阵如下: 这个图的树形结构应该是这样的
我必须创建两个类:NonBinaryTree和SingleNode类,包含一些处理节点和整个树的方法(在NonBinaryTree类中)。我在使用队列(先进先出类型)实现非二叉树的BFS(层次顺序)遍历时遇到过问题。由于二叉树有很多资源,每个节点最多有两个子节点,我还没有找到任何可以帮助我解决非二叉树问题的资源。 到目前为止,我做了这个代码: 我的树: 在此处输入图像描述 我需要按以下顺序处理节点
我正在尝试在UI上显示树结构。但是得到一个错误。 无法绑定到“target”,因为它不是“i”的已知属性。(“v*ngFor=”让文件项 虽然这个属性存在于我的json文件中,如下所示: 我的html文件如下: 我无法找出这次失败的原因。我已经尝试了所有可能的条件,我可以申请使它工作。请帮我解决这个问题
我有一个类别树,由以下内容表示。 这给出了一个dataframe,如下所示: 树中最高的节点的parent_id等于-1,因此树可以用图形表示如下: 我需要生成以下DataFrame。 该树是动态生成的,可以具有任意数量的级别,因此下面的树 应产生以下结果:
递归树组,父节点selected为true且partiallySelected为fasle的时候,所有子节点childrens下的节点的selected则也修改为true syncChildrenStatus(arr)后 希望得到的