Consider I want to traverse some of the nodes of a tree-like structure using Stream API (similar questions: [1], [2], [3]). The first implementation coming to mind would be:
abstract class Node {
abstract Collection<Node> getChildren();
final Stream<Node> stream() {
return Stream.concat(Stream.of(this), this.getChildren().stream().flatMap(Node::stream));
}
}
The above stream()
implementation has the following features:
- It's "almost lazy", in a sense that only the immediate children of the root node will be retrieved during a stream creation (children of other internal nodes will be queried as necessary).
- It exhibits a DFS traversal order.
Now consider I have a large hierarchy, getChildren()
operation is costly, and I'm looking for any Node
matching some predicate:
final Node tree = ...;
final Predicate<Node> p = ...;
tree.stream().filter(p).findAny();
- How do I make my
stream()
implementation "completely lazy"? I don't want children of a node queried if the node itself already matches the predicate. I'm looking for a lazy version ofStream.concat()
with a signature of(Stream<T> a, Supplier<Stream<T>> b)
. - How do I implement a BFS traversal order instead (using Stream API)?