我想编写一个Java 8 stream().collect
函数,它返回一个List<T>
,其中包含层次结构中节点的所有子节点和子节点。例如TreeItem<T>
getChildren()
和所有孩子的孩子等等,将其缩减为单个列表。
顺便说一句,这是我作为通用方法的最终解决方案。非常有效且非常有用。
public static <T> Stream<T> treeStream(T root, boolean includeRoot, Function<T, Stream<? extends T>> nextChildren)
{
Stream<T> stream = nextChildren.apply(root).flatMap(child -> treeStream(child, true, nextChildren));
return includeRoot ? Stream.concat(Stream.ofNullable(root), stream) : stream;
}
答案 0 :(得分:0)
您必须使用递归函数展平树。你在这里有一个例子:http://squirrel.pl/blog/2015/03/04/walking-recursive-data-structures-using-java-8-streams/
答案 1 :(得分:0)
为了不丢弃堆栈溢出,有一种方法可以用堆中的队列替换堆栈。
此解决方案从迭代器创建流,该迭代器懒惰地导航保存Queue中的下一个项目的树。
根据队列遍历的类型,可以是depth first或breadth first
class TreeItem {
Collection<TreeItem> children = new ArrayList<>();
}
Stream<TreeItem> flatten(TreeItem root) {
Iterator<TreeItem> iterator = new Iterator<TreeItem>() {
Queue<TreeItem> queue = new LinkedList<>(Collections.singleton(root)); //breadth first
// Queue<TreeItem> queue = Collections.asLifoQueue(new LinkedList<>(Collections.singleton(root))); //depth first
@Override public boolean hasNext() {
return !queue.isEmpty();
}
@Override public TreeItem next() {
TreeItem next = queue.poll();
queue.addAll(next.children);
return next;
}
};
return StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator, 0), false);
}