当前位置: 首页 > 知识库问答 >
问题:

其他流的笛卡尔乘积流,每个元素作为一个列表?

姚航
2023-03-14

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

我看过这个问题 - 这个问题使用了一个聚合器,它是一个二进制运算符(采用两个类似类型的项目并生成一个相同类型的项目)。我希望最终结果中的项目是列表,而不是输入流中元素的类型。

具体来说,假设我想要的函数称为产品,如下所示:

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() 生成的,那么如果这些流的供应商在绝对需要时才被执行,那就太好了。

共有2个答案

燕智
2023-03-14

你可以实现这样的东西:

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]

另请参阅:查找 2 个列表的笛卡尔乘积

萧鹏云
2023-03-14

可能的解决方案如下:

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

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

 类似资料:
  • 的结果将是二维数组: 我试图做的是使用流在Java中编写这个笛卡尔乘积函数。 到目前为止,我有以下Java版本: 我对问题的猜测是: 我需要在某个地方使用收集器(可能在之后) 标识的数据类型错误

  • 例如,对于{A,B}和{X,Y}这两个流,我希望它生成值流{AX,AY,BX,BY}(简单的串联用于聚合字符串)。到目前为止,我已经想出了这段代码: 这是我想要的用例: 预期结果:。 溪流消耗在哪里?按平面地图?很容易修好吗?

  • 问题内容: 我想创建一个方法,该方法创建元素流,这些元素流是多个给定流的笛卡尔积(由二元运算符最后汇总为相同类型)。请注意,参数和结果都是流, 而不是 集合。 例如,对于 {A,B} 和 {X,Y}的 两个流,我希望它产生值 {AX,AY,BX,BY}的流 (简单串联用于聚集字符串)。到目前为止,我想出了以下代码: 这是我想要的用例: 预期结果:。 另一个例子: 预期结果:。 但是,如果我运行代码

  • 我有以下收藏类型: 我希望根据集合中每个键的单个值为每个创建唯一的组合。

  • 问题内容: 以下代码适用于,它是否也返回重复的笛卡尔积,如果是,如何获得唯一的笛卡尔积? 当我传递包含列表的列表时,这似乎也不起作用 问题答案: 要仅获取唯一元素,可以使用这样的set表示法( 注意: 这不能保证顺序) 或根据Paul Draper的评论,我们可以像这样 如果您也想维护订单 要使您的程序可以使用列表列表,只需将函数声明从 至

  • 我正在尝试对一个后端服务器进行负载测试,并将一些配置解析到一个标签对象中。我正在尝试生成< code>Label对象的笛卡尔乘积,这将是一个< code>Metric对象。 我有一个 方法添加 我试图以迭代/递归的方式做到这一点,但它变得非常复杂和混乱。我检查了是否有java8替代方案。如果我能够获得