用流递归展平列表

时间:2018-10-05 16:58:16

标签: java java-stream

我具有内部节点和终端节点的树状结构:

public interface Node
{
}

public class InternalNode implements Node {
    private List<Node> nodes;
}

public class TerminalNode implements Node {
    private String label;
}

我现在有一个List<Node>,我想弄平。在这里,展平意味着我要用其子级递归替换内部节点,直到所有内部节点都被终端替换为止。

我想出了这个功能:

private static List<Node> flatten(final List<Node> nodes) {
    return nodes
            .stream()
            .map(node -> {
                if (node instanceof InternalNode) {
                    return flatten(((InternalNode) node).getNodes());
                }
                return Collections.singletonList(node);
            })
            .flatMap(List::stream)
            .collect(Collectors.toList());
}

这似乎可以做到。但是,我想知道是否有更好的实现方案。似乎很奇怪,我首先必须通过TerminalNodeList<TerminalNode>包装到单例列表(类型为Collections.singletonList(node))中,然后再通过以下方式将那个单例列表再次转换回该节点flatMap(List::stream)

是否有一种方法可以避免终端节点出现无用的Collections.singletonList(node)后跟flatMap(List::stream)的情况?

1 个答案:

答案 0 :(得分:8)

您可以直接使用flatMap:

private static Stream<TerminalNode> flatten(final List<Node> nodes) {
    return nodes
            .stream()
            .flatMap(node -> {
                if (node instanceof InternalNode) {
                    return flatten(((InternalNode) node).getNodes());
                }
                return Stream.of((TerminalNode) node);
            });
}

如果要使用列表,则只需收集该方法调用的结果即可。