【问题标题】:Stream of cartesian product of other streams, each element as a List?其他流的笛卡尔积流,每个元素作为一个列表?
【发布时间】:2017-05-22 13:24:42
【问题描述】:

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

我查看了this question——该问题使用了一个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);

应该打印:

[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]

理想情况下,我希望此操作尽可能懒惰。例如,如果输入流是由Stream.generate() 生成的,那么如果这些流的提供者在绝对需要时才执行,那就太好了。

【问题讨论】:

    标签: java java-8 java-stream cartesian-product


    【解决方案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);
    }
    

    产品调用返回一个Stream&lt;List&lt;String&gt;&gt; 结果,打印为

    [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]
    

    【讨论】:

      【解决方案2】:

      你可以这样实现:

      List<Stream<String>> listStreams = List.of(
              Stream.of("A", "B", "C", "D"),
              Stream.of("I", "J", "K"),
              Stream.of("Y", "Z"));
      
      Stream<List<String>> streamLists = listStreams.stream()
              // represent each list element as SingletonList<Object>
              .map(stream -> stream.map(Collections::singletonList))
              // summation of pairs of inner lists
              .reduce((stream1, stream2) -> {
                  // list of lists from second stream
                  List<List<String>> list2 = stream2.collect(Collectors.toList());
                  // append to the first stream
                  return stream1.flatMap(inner1 -> list2.stream()
                          // combinations of inner lists
                          .map(inner2 -> {
                              List<String> list = new ArrayList<>();
                              list.addAll(inner1);
                              list.addAll(inner2);
                              return list;
                          }));
              }).orElse(Stream.empty());
      
      // output
      streamLists.forEach(System.out::println);
      

      输出:

      [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]
      

      另见:Find cartesian product of 2 lists

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-12-14
        • 2012-01-03
        • 1970-01-01
        • 2021-10-22
        • 2022-11-17
        • 2013-11-25
        • 1970-01-01
        相关资源
        最近更新 更多