我的地图如下。
{“A”:[“A1”,“A2”,“A3”],“B”:[“B1”,“B2”,“B3”]}
我想获得如下数据
A1, B1
A1, B2
A1, B3
A2, B1
A2, B2
...
我试过以下
for( String aKey : map.get("A"))
for( String bKey: map.get("B"))
// work with aKey + bKey
但这不是我想要的代码,因为地图数据是动态且无法预料的。
所以我应该得到如下所示的地图数据,但不能按我的意愿制作
for( String key : map.keySet())
for( String values : map.get(key))
// unable to make data I want
答案 0 :(得分:0)
您已经正确地理解,您无法创建带有静态嵌套循环集的任意数据的笛卡尔积。您需要的是一组动态的嵌套循环。我以为您尝试了最后一个代码段。似乎您也了解到,需要的嵌套循环数与数据中设置的数目一样多。问题仍然存在:如何对动态数量的嵌套循环进行编程。
基本上,有两种方法可以动态地嵌套循环:递归和迭代。两者都达到相同的结果,并且性能(在时间和内存方面)应该相似。如果实施得好,那就是。
以下是两个类似的问题,其中一个明确要求迭代解决方案:
尝试了解两者。您的大脑可能更喜欢一个,但至少要同时了解两个都值得。
递归方法的附加问题,因为可以说递归很难理解:Simulating nested loops
答案 1 :(得分:0)
如果您有一个列表映射,您可以使用 map 和 reduce 方法获得其值的 笛卡尔积。此代码可用于任意数量的列表。
// a map of lists
Map<String, List<String>> map = new TreeMap<>();
map.put("A", Arrays.asList("A1", "A2"));
map.put("B", Arrays.asList("B1", "B2"));
map.put("C", Arrays.asList("C1", "C2"));
// cartesian product of the map values
List<List<String>> cp = map.values().stream()
// represent each element of a list as a singleton list
.map(list -> list.stream().map(Arrays::asList)
// Stream<List<List<String>>>
.collect(Collectors.toList()))
// summation of pairs of list into a single list
.reduce((list1, list2) -> list1.stream()
// combinations of inner lists
.flatMap(inner1 -> list2.stream()
// concatenate into a single list
.map(inner2 -> Stream.of(inner1, inner2)
.flatMap(List::stream)
.collect(Collectors.toList())))
// list of combinations
.collect(Collectors.toList()))
// otherwise an empty list
.orElse(Collections.emptyList());
// output
map.forEach((k, v) -> System.out.println(k + ": " + v));
cp.forEach(System.out::println);
输出:
A: [A1, A2]
B: [B1, B2]
C: [C1, C2]
[A1, B1, C1]
[A1, B1, C2]
[A1, B2, C1]
[A1, B2, C2]
[A2, B1, C1]
[A2, B1, C2]
[A2, B2, C1]
[A2, B2, C2]
另见:How to create cartesian product over arbitrary groups of numbers in Java?