其他流的笛卡尔积的流,每个元素作为List? [英] Stream of cartesian product of other streams, each element as a List?

查看:161
本文介绍了其他流的笛卡尔积的流,每个元素作为List?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

How can I implement a function using Java 8 to take some number of streams, and produce a stream in which each element is a list consisting of one member of the Cartesian product of the streams?

我看过这个问题 - 该问题使用的聚合器是 BinaryOperator (取两个类似的类型并生成相同类型的项目) 。我希望最终结果中的项目是 List s而不是输入流中元素的类型。

I've looked at this question -- that question uses an aggregator that is a BinaryOperator (taking two items of like type and producing an item of the same type). I'd like the items in the end result to be Lists rather than the types of the elements in the input streams.

具体而言,假设我所需的函数名为 product ,以下内容:

Concretely, supposing my desired function is called product, the following:

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

Ideally, I'd like for this operation to be as lazy as possible. For example, if the input streams are produced by Stream.generate(), it'd be great if the suppliers of those streams weren't executed until absolutely needed.

推荐答案

可能的解决方案如下:

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< List<字符串>> 结果打印为

The product-call returns a Stream<List<String>> result which prints as

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

这篇关于其他流的笛卡尔积的流,每个元素作为List?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆