如何使用Java 8流创建笛卡尔积?

49

我有以下集合类型:

Map<String, Collection<String>> map;

我想要创建每个键中map.size()个独特组合,每个组合来自集合中的单个值。

例如,假设地图如下所示:

A, {a1, a2, a3, ..., an}
B, {b1, b2, b3, ..., bn}
C, {c1, c2, c3, ..., cn}

我想要得到的结果是一个List<Set<String>>,看起来类似于以下内容(顺序不重要,它只需要是一个“完整”的结果,包含所有可能的组合):

{a1, b1, c1},
{a1, b1, c2},
{a1, b1, c3},
{a1, b2, c1},
{a1, b2, c2},
{a1, b2, c3},
...
{a2, b1, c1},
{a2, b1, c2},
...
{a3, b1, c1},
{a3, b1, c2},
...
{an, bn, cn}

这基本上是一个计数问题,但我想看看是否可以使用Java 8流实现解决方案。

11个回答

0
您可以按照以下方式使用Stream.reduce方法。

在线试用!

Map<String, List<String>> map = new LinkedHashMap<>();
map.put("A", List.of("a1", "a2", "a3"));
map.put("B", List.of("b1", "b2", "b3"));
map.put("C", List.of("c1", "c2", "c3"));

List<List<String>> cartesianProduct = map.values().stream()
        // represent each list element as a singleton list
        .map(list -> list.stream().map(Collections::singletonList)
                .collect(Collectors.toList()))
        // reduce the stream of lists to a single list by
        // sequentially summing pairs of elements of two lists
        .reduce((list1, list2) -> list1.stream()
                // combinations of inner lists
                .flatMap(first -> list2.stream()
                        // merge two inner lists into one
                        .map(second -> Stream.of(first, second)
                                .flatMap(List::stream)
                                .collect(Collectors.toList())))
                // list of combinations
                .collect(Collectors.toList()))
        // List<List<String>>
        .orElse(Collections.emptyList());

// column-wise output
int rows = 9;
IntStream.range(0, rows)
        .mapToObj(i -> IntStream.range(0, cartesianProduct.size())
                .filter(j -> j % rows == i)
                .mapToObj(j -> cartesianProduct.get(j).toString())
                .collect(Collectors.joining("  ")))
        .forEach(System.out::println);

输出:

[a1, b1, c1]  [a2, b1, c1]  [a3, b1, c1]
[a1, b1, c2]  [a2, b1, c2]  [a3, b1, c2]
[a1, b1, c3]  [a2, b1, c3]  [a3, b1, c3]
[a1, b2, c1]  [a2, b2, c1]  [a3, b2, c1]
[a1, b2, c2]  [a2, b2, c2]  [a3, b2, c2]
[a1, b2, c3]  [a2, b2, c3]  [a3, b2, c3]
[a1, b3, c1]  [a2, b3, c1]  [a3, b3, c1]
[a1, b3, c2]  [a2, b3, c2]  [a3, b3, c2]
[a1, b3, c3]  [a2, b3, c3]  [a3, b3, c3]

另请参阅:使用Java递归生成字符串排列


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接