嵌套循环的地图和减少方法
一个外部流可以轻松地转换为parallel
,在某些情况下可以减少计算时间。内部迭代使用循环实现。
在线尝试!
public static <T> List<List<T>> cartesianProduct(Map<T, List<T>> map) {
if (map == null) return Collections.emptyList();
return map.values().stream().parallel()
.filter(list -> list != null && list.size() > 0)
.map(list -> {
List<List<T>> nList = new ArrayList<>(list.size());
for (T e : list) nList.add(Collections.singletonList(e));
return nList;
})
.reduce((list1, list2) -> {
int size = list1.size() * list2.size();
List<List<T>> list = new ArrayList<>(size);
for (List<T> inner1 : list1)
for (List<T> inner2 : list2) {
List<T> inner = new ArrayList<>();
inner.addAll(inner1);
inner.addAll(inner2);
list.add(inner);
}
return list;
}).orElse(Collections.emptyList());
}
public static void main(String[] args) {
Map<String, List<String>> map = new LinkedHashMap<>();
map.put("A", Arrays.asList("A1", "A2", "A3", "A4"));
map.put("B", Arrays.asList("B1", "B2", "B3"));
map.put("C", Arrays.asList("C1", "C2"));
List<List<String>> cp = cartesianProduct(map);
int rows = 6;
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cp.size(); j++)
System.out.print(j % rows == i ? cp.get(j) + " " : "");
System.out.println();
}
}
输出:
[A1, B1, C1] [A2, B1, C1] [A3, B1, C1] [A4, B1, C1]
[A1, B1, C2] [A2, B1, C2] [A3, B1, C2] [A4, B1, C2]
[A1, B2, C1] [A2, B2, C1] [A3, B2, C1] [A4, B2, C1]
[A1, B2, C2] [A2, B2, C2] [A3, B2, C2] [A4, B2, C2]
[A1, B3, C1] [A2, B3, C1] [A3, B3, C1] [A4, B3, C1]
[A1, B3, C2] [A2, B3, C2] [A3, B3, C2] [A4, B3, C2]
另请参阅:如何从多个列表中获取笛卡尔积?
Collection.forEach
不是 Stream API 的一部分)。您可以用传统的for-in
循环替换.forEach
,这样您的代码就能兼容 Java 5。此外,请注意您将所有组合都存储在内存中。虽然对于 OP 来说这似乎没问题,但如果输入更大,这可能会成为问题。最后,没有简单的方法来并行化它。 - Tagir Valeev