其他流的笛卡尔积的流,每个元素作为List? [英] Stream of cartesian product of other streams, each element as a 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 List
s 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屋!