Java Stream收集所有孩子

时间:2016-07-08 11:58:23

标签: java-8 java-stream hierarchical-data children collectors

我想编写一个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;
}

2 个答案:

答案 0 :(得分:0)

您必须使用递归函数展平树。你在这里有一个例子:http://squirrel.pl/blog/2015/03/04/walking-recursive-data-structures-using-java-8-streams/

答案 1 :(得分:0)

为了不丢弃堆栈溢出,有一种方法可以用堆中的队列替换堆栈。

此解决方案从迭代器​​创建流,该迭代器懒惰地导航保存Queue中的下一个项目的树。

根据队列遍历的类型,可以是depth firstbreadth 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);
}