其他流的笛卡尔积的流,每个元素作为List?

pho*_*ser 7 java cartesian-product java-8 java-stream

如何使用Java 8实现一个函数来获取一些流,并生成一个流,其中每个元素都是一个由流的笛卡尔积的一个成员组成的列表?

我已经看过这个问题 - 这个问题使用了一个聚合器BinaryOperator(采用类似类型的两个项目并生成相同类型的项目).我希望最终结果中的项目是Lists而不是输入流中的元素类型.

具体地说,假设我调用product了我想要的函数,如下:

Stream<List<String>> result =
    product(
        Stream.of("A", "B", "C", "D"), 
        Stream.of("I", "J", "K),
        Stream.of("Y", "Z")
    );

result.forEach(System.out::println);
Run Code Online (Sandbox Code Playgroud)

应该打印:

[A, I, Y]
[A, I, Z]
[A, J, Y]
[A, J, Z]
[A, K, Y]
[A, K, Z]
[B, I, Y]
...
[D, K, Y]
[D, K, Z]
Run Code Online (Sandbox Code Playgroud)

理想情况下,我希望这个操作尽可能地懒惰.例如,如果输入流是由生成的Stream.generate(),那么如果这些流的供应商在绝对需要之前没有被执行,那就太好了.

mar*_*rco 1

一种可能的解决方案如下:

private static <T> Stream<List<T>> product(Stream<T>... streams) {
    if (streams.length == 0) {
        return Stream.empty();
    }
    List<List<T>> cartesian = streams[streams.length - 1]
            .map(x -> Collections.singletonList(x))
            .collect(Collectors.toList());
    for (int i = streams.length - 2; i >= 0; i--) {
        final List<List<T>> previous = cartesian;
        cartesian = streams[i].flatMap(x -> previous.stream().map(p -> {
            final List<T> list = new ArrayList<T>(p.size() + 1);
            list.add(x);
            list.addAll(p);
            return list;
        })).collect(Collectors.toList());
    }
    return cartesian.stream();
}

public static void main(String... args) {
    final Stream<List<String>> result =
            product(
                    Stream.of("A", "B", "C", "D"),
                    Stream.of("I", "J", "K"),
                    Stream.of("Y", "Z")
            );

    result.forEach(System.out::println);
}
Run Code Online (Sandbox Code Playgroud)

产品调用返回一个Stream<List<String>>结果,打印为

[A, I, Y]
[A, I, Z]
[A, J, Y]
[A, J, Z]
[A, K, Y]
[A, K, Z]
[B, I, Y]
[B, I, Z]
[B, J, Y]
[B, J, Z]
[B, K, Y]
[B, K, Z]
[C, I, Y]
[C, I, Z]
[C, J, Y]
[C, J, Z]
[C, K, Y]
[C, K, Z]
[D, I, Y]
[D, I, Z]
[D, J, Y]
[D, J, Z]
[D, K, Y]
[D, K, Z]
Run Code Online (Sandbox Code Playgroud)