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)?
concat
(alone) but the current implementation offlatMap
that affects the laziness. You have to think carefully whether you want to fix what the JRE broke. If you want to proceed, have a look at this answer… – Holger