笛卡尔乘积
两个集合X和Y的笛卡尓积(Cartesian product),又称直积,表示为X×Y,第一个对象是X的成员而第二个对象是Y的所有可能有序对的其中一个成员。
举例
假设集合A={a, b},集合B={0, 1, 2},则两个集合的笛卡尔积为{(a, 0), (a, 1), (a, 2), (b, 0), (b, 1), (b, 2)}
Java 核心实现
/**
* Discription: 笛卡尔乘积算法
* 把一个List{[1,2],[A,B],[a,b]} 转化成
* List{[1,A,a],[1,A,b],[1,B,a],[1,B,b],[2,A,a],[2,A,b],[2,B,a],[2,B,b]} 数组输出
*
* @param dimensionValue
* 原List
* @param result
* 通过乘积转化后的数组
* @param layer
* 中间参数
* @param currentList
* 中间参数
*/
public void descartes(List<List<T>> dimensionValue, List<List<T>> result, int layer, List<T> currentList) {
if (layer < dimensionValue.size() - 1) {
if (dimensionValue.get(layer).size() == 0) {
descartes(dimensionValue, result, layer + 1, currentList);
} else {
for (int i = 0; i < dimensionValue.get(layer).size(); i++) {
List<T> list = new ArrayList<T>(currentList);
list.add(dimensionValue.get(layer).get(i));
descartes(dimensionValue, result, layer + 1, list);
}
}
} else if (layer == dimensionValue.size() - 1) {
if (dimensionValue.get(layer).size() == 0) {
result.add(currentList);
} else {
for (int i = 0; i < dimensionValue.get(layer).size(); i++) {
List<T> list = new ArrayList<T>(currentList);
list.add(dimensionValue.get(layer).get(i));
result.add(list);
}
}
}
}
验证方法
public class Demo{
/**
* 例:将 modelList 按type分组位后得到 (取ID为例)
* [type = 1] = [1, 2, 3],
* [type = 2] = [4],
* [type = 3] = [5, 6, 7]
* 求笛卡尔积的结果应为[1, 4, 5] ,[1, 4, 6], [1, 4, 7],[2, 4, 5],[2, 4, 6],[2, 4, 7],[3, 4, 5],[3, 4, 6],[3, 4, 7]
*/
@Test
public void listToDescartes(){
List<Model> modelList = Lists.newArrayList();
modelList.add(new Model(1,"a", "zhuoli", 1 ));
modelList.add(new Model(2,"b", "zhuoli", 1));
modelList.add(new Model(3,"c", "Alice", 1));
modelList.add(new Model(4,"d", "zhuoli", 2));
modelList.add(new Model(5,"e", "zhuoli", 3));
modelList.add(new Model(6,"f", "Michael", 3));
modelList.add(new Model(7,"g", "Michael", 3));
// 按指定字段(type)分组
Map<Integer, List<Model>> modelMap = modelList.stream().collect(Collectors.groupingBy(Model::getType));
Collection<List<Model>> mapValues = modelMap.values();
List<List<Model>> dimensionValue = new ArrayList<>(mapValues); // 原List
List<List<Model>> result = new ArrayList<>(); // 返回集合
new ArrayUtils().descartes(dimensionValue, result, 0, new ArrayList<Model>());
for (List<Model> models : result) {
List<Integer> resList = new ArrayList<>();
for (Model model : models) {
resList.add(model.getId());
}
System.out.println(resList.toString());
}
}
@Data
@AllArgsConstructor
@ToString
class Model {
private Integer id;
private String name;
private String author;
private Integer type;
}
}
验证结果