最近遇到一个需要计算笛卡尔积的需求,由于乘积结果较小,因此可以使用递归方法,这样也方便理解一些。
笛卡尔积实际就是在一个类似矩阵的结果集中,从每行逐个取出元素进行组合的结果,直到最后一行就可以跳出循环。
搞清楚大致实现原理后,就可以敲代码啦~
我的实现方法没有考虑效率,只是用于抛砖引玉:
class DescartesTest {
@Test
void descartes() {
List<String> list1 = new ArrayList<>();
list1.add("a1");
list1.add("a2");
list1.add("a3");
List<String> list2 = new ArrayList<>();
list2.add("b1");
list2.add("b2");
List<String> list3 = new ArrayList<>();
list3.add("c1");
list3.add("c2");
List<List<String>> dimensionValues = new ArrayList<>();
dimensionValues.add(list1);
dimensionValues.add(list2);
dimensionValues.add(list3);
List<String> descartes = descartes(dimensionValues, 0, StringUtils.EMPTY, new ArrayList<>());
descartes.forEach(System.out::println);
}
private List<String> descartes(List<List<String>> dimensionValues, int position, String originCode,
List<String> result) {
// if (CollectionUtils.isEmpty(dimensionValues) || position >= dimensionValues.size()) {
// return result;
// }
// 获取指定行数据
List<String> rowValue = dimensionValues.get(position);
for (String code : rowValue) {
// 第一行不用拼接,直接copy,第二行开始需要在末尾拼接code
String resultCode = position == 0 ? code : originCode + ";" + code;
// 如果当前位置是最后一行,则可以添加最终resultCode构建结果
if (position == dimensionValues.size() - 1) {
result.add(resultCode);
} else {
// 否则进入下一行
descartes(dimensionValues, position + 1, resultCode, result);
}
}
return result;
}
}
最终输出结果如下图所示: