|
@@ -1,163 +1,301 @@
|
|
|
package cn.iocoder.yudao.module.product.service.spu;
|
|
|
|
|
|
+import cn.iocoder.yudao.framework.common.exception.ServiceException;
|
|
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
|
|
+import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
|
|
|
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
|
|
|
-import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuCreateReqVO;
|
|
|
-import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuPageReqVO;
|
|
|
-import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuRespVO;
|
|
|
-import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuUpdateReqVO;
|
|
|
+import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyRespVO;
|
|
|
+import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueRespVO;
|
|
|
+import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuCreateOrUpdateReqVO;
|
|
|
+import cn.iocoder.yudao.module.product.controller.admin.spu.vo.*;
|
|
|
+import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppSpuPageReqVO;
|
|
|
+import cn.iocoder.yudao.module.product.controller.app.spu.vo.AppSpuPageRespVO;
|
|
|
+import cn.iocoder.yudao.module.product.convert.spu.ProductSpuConvert;
|
|
|
+import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO;
|
|
|
import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO;
|
|
|
import cn.iocoder.yudao.module.product.dal.mysql.spu.ProductSpuMapper;
|
|
|
-import org.junit.jupiter.api.Disabled;
|
|
|
+import cn.iocoder.yudao.module.product.enums.spu.ProductSpuSpecTypeEnum;
|
|
|
+import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum;
|
|
|
+import cn.iocoder.yudao.module.product.service.brand.ProductBrandServiceImpl;
|
|
|
+import cn.iocoder.yudao.module.product.service.category.ProductCategoryServiceImpl;
|
|
|
+import cn.iocoder.yudao.module.product.service.property.ProductPropertyService;
|
|
|
+import cn.iocoder.yudao.module.product.service.property.ProductPropertyValueService;
|
|
|
+import cn.iocoder.yudao.module.product.service.sku.ProductSkuServiceImpl;
|
|
|
+import com.google.common.collect.Lists;
|
|
|
+import org.junit.jupiter.api.Assertions;
|
|
|
import org.junit.jupiter.api.Test;
|
|
|
+import org.mockito.Mockito;
|
|
|
+import org.springframework.boot.test.mock.mockito.MockBean;
|
|
|
import org.springframework.context.annotation.Import;
|
|
|
|
|
|
import javax.annotation.Resource;
|
|
|
+import java.util.ArrayList;
|
|
|
+import java.util.List;
|
|
|
+import java.util.Map;
|
|
|
+import java.util.stream.Collectors;
|
|
|
+import java.util.stream.Stream;
|
|
|
|
|
|
-import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId;
|
|
|
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
|
|
|
-import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
|
|
|
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
|
|
|
-import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.SPU_NOT_EXISTS;
|
|
|
-import static org.junit.jupiter.api.Assertions.*;
|
|
|
|
|
|
/**
|
|
|
-* {@link ProductSpuServiceImpl} 的单元测试类
|
|
|
-*
|
|
|
-* @author 芋道源码
|
|
|
-*/
|
|
|
+ * {@link ProductSpuServiceImpl} 的单元测试类
|
|
|
+ *
|
|
|
+ * @author 芋道源码
|
|
|
+ */
|
|
|
@Import(ProductSpuServiceImpl.class)
|
|
|
public class ProductSpuServiceImplTest extends BaseDbUnitTest {
|
|
|
|
|
|
@Resource
|
|
|
- private ProductSpuServiceImpl spuService;
|
|
|
+ private ProductSpuServiceImpl productSpuService;
|
|
|
|
|
|
@Resource
|
|
|
- private ProductSpuMapper ProductSpuMapper;
|
|
|
+ private ProductSpuMapper productSpuMapper;
|
|
|
+
|
|
|
+
|
|
|
+ @MockBean
|
|
|
+ private ProductSkuServiceImpl productSkuService;
|
|
|
+
|
|
|
+ @MockBean
|
|
|
+ private ProductCategoryServiceImpl categoryService;
|
|
|
+
|
|
|
+ @MockBean
|
|
|
+ private ProductBrandServiceImpl brandService;
|
|
|
+
|
|
|
+ @MockBean
|
|
|
+ private ProductPropertyService productPropertyService;
|
|
|
+
|
|
|
+ @MockBean
|
|
|
+ private ProductPropertyValueService productPropertyValueService;
|
|
|
+
|
|
|
|
|
|
@Test
|
|
|
public void testCreateSpu_success() {
|
|
|
// 准备参数
|
|
|
- ProductSpuCreateReqVO reqVO = randomPojo(ProductSpuCreateReqVO.class);
|
|
|
+ ProductSpuCreateReqVO createReqVO = randomPojo(ProductSpuCreateReqVO.class, o -> {
|
|
|
+ o.setSpecType(ProductSpuSpecTypeEnum.DISABLE.getType());
|
|
|
+ o.setStatus(ProductSpuStatusEnum.ENABLE.getStatus());
|
|
|
+ });
|
|
|
+
|
|
|
+ // 校验SKU
|
|
|
+ List<ProductSkuCreateOrUpdateReqVO> skuCreateReqList = createReqVO.getSkus();
|
|
|
+
|
|
|
+ Long spu = productSpuService.createSpu(createReqVO);
|
|
|
+ ProductSpuDO productSpuDO = productSpuMapper.selectById(spu);
|
|
|
+
|
|
|
+ createReqVO.setMarketPrice(CollectionUtils.getMaxValue(skuCreateReqList, ProductSkuCreateOrUpdateReqVO::getMarketPrice));
|
|
|
+ createReqVO.setMaxPrice(CollectionUtils.getMaxValue(skuCreateReqList, ProductSkuCreateOrUpdateReqVO::getPrice));
|
|
|
+ createReqVO.setMinPrice(CollectionUtils.getMinValue(skuCreateReqList, ProductSkuCreateOrUpdateReqVO::getPrice));
|
|
|
+ createReqVO.setTotalStock(CollectionUtils.getSumValue(skuCreateReqList, ProductSkuCreateOrUpdateReqVO::getStock, Integer::sum));
|
|
|
+
|
|
|
+ assertPojoEquals(createReqVO, productSpuDO);
|
|
|
|
|
|
- // 调用
|
|
|
- Long spuId = spuService.createSpu(reqVO);
|
|
|
- // 断言
|
|
|
- assertNotNull(spuId);
|
|
|
- // 校验记录的属性是否正确
|
|
|
- ProductSpuDO spu = ProductSpuMapper.selectById(spuId);
|
|
|
- assertPojoEquals(reqVO, spu);
|
|
|
}
|
|
|
|
|
|
@Test
|
|
|
public void testUpdateSpu_success() {
|
|
|
- // mock 数据
|
|
|
- ProductSpuDO dbSpu = randomPojo(ProductSpuDO.class);
|
|
|
- ProductSpuMapper.insert(dbSpu);// @Sql: 先插入出一条存在的数据
|
|
|
+ // 准备参数
|
|
|
+ ProductSpuDO createReqVO = randomPojo(ProductSpuDO.class);
|
|
|
+ productSpuMapper.insert(createReqVO);
|
|
|
// 准备参数
|
|
|
ProductSpuUpdateReqVO reqVO = randomPojo(ProductSpuUpdateReqVO.class, o -> {
|
|
|
- o.setId(dbSpu.getId()); // 设置更新的 ID
|
|
|
+ o.setId(createReqVO.getId()); // 设置更新的 ID
|
|
|
+ o.setSpecType(ProductSpuSpecTypeEnum.DISABLE.getType());
|
|
|
+ o.setStatus(ProductSpuStatusEnum.DISABLE.getStatus());
|
|
|
});
|
|
|
-
|
|
|
// 调用
|
|
|
- spuService.updateSpu(reqVO);
|
|
|
+ productSpuService.updateSpu(reqVO);
|
|
|
+
|
|
|
+ List<ProductSkuCreateOrUpdateReqVO> skuCreateReqList = reqVO.getSkus();
|
|
|
+ reqVO.setMarketPrice(CollectionUtils.getMaxValue(skuCreateReqList, ProductSkuCreateOrUpdateReqVO::getMarketPrice));
|
|
|
+ reqVO.setMaxPrice(CollectionUtils.getMaxValue(skuCreateReqList, ProductSkuCreateOrUpdateReqVO::getPrice));
|
|
|
+ reqVO.setMinPrice(CollectionUtils.getMinValue(skuCreateReqList, ProductSkuCreateOrUpdateReqVO::getPrice));
|
|
|
+ reqVO.setTotalStock(CollectionUtils.getSumValue(skuCreateReqList, ProductSkuCreateOrUpdateReqVO::getStock, Integer::sum));
|
|
|
+
|
|
|
// 校验是否更新正确
|
|
|
- ProductSpuDO spu = ProductSpuMapper.selectById(reqVO.getId()); // 获取最新的
|
|
|
+ ProductSpuDO spu = productSpuMapper.selectById(reqVO.getId()); // 获取最新的
|
|
|
assertPojoEquals(reqVO, spu);
|
|
|
}
|
|
|
|
|
|
@Test
|
|
|
- public void testUpdateSpu_notExists() {
|
|
|
+ public void testValidateSpuExists_exception() {
|
|
|
+ ProductSpuUpdateReqVO reqVO = randomPojo(ProductSpuUpdateReqVO.class, o -> {
|
|
|
+ o.setSpecType(ProductSpuSpecTypeEnum.DISABLE.getType());
|
|
|
+ o.setStatus(ProductSpuStatusEnum.DISABLE.getStatus());
|
|
|
+ });
|
|
|
+ // 调用
|
|
|
+ Assertions.assertThrows(ServiceException.class, () -> productSpuService.updateSpu(reqVO));
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ void deleteSpu() {
|
|
|
+ // 准备参数
|
|
|
+ ProductSpuDO createReqVO = randomPojo(ProductSpuDO.class);
|
|
|
+ productSpuMapper.insert(createReqVO);
|
|
|
+
|
|
|
+ // 调用
|
|
|
+ productSpuService.deleteSpu(createReqVO.getId());
|
|
|
+
|
|
|
+ Assertions.assertNull(productSpuMapper.selectById(createReqVO.getId()));
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ void getSpuDetail() {
|
|
|
+ // 准备spu参数
|
|
|
+ ProductSpuDO createReqVO = randomPojo(ProductSpuDO.class, o -> {
|
|
|
+ o.setSpecType(ProductSpuSpecTypeEnum.DISABLE.getType());
|
|
|
+ });
|
|
|
+ productSpuMapper.insert(createReqVO);
|
|
|
+
|
|
|
+ // 创建两个属性
|
|
|
+ ArrayList<ProductPropertyRespVO> productPropertyRespVOS = Lists.newArrayList(
|
|
|
+ randomPojo(ProductPropertyRespVO.class),
|
|
|
+ randomPojo(ProductPropertyRespVO.class));
|
|
|
+
|
|
|
+ // 所有属性值
|
|
|
+ ArrayList<ProductPropertyValueRespVO> productPropertyValueRespVO = new ArrayList<>();
|
|
|
+
|
|
|
+ // 每个属性创建属性值
|
|
|
+ productPropertyRespVOS.forEach(v -> {
|
|
|
+ ProductPropertyValueRespVO productPropertyValueRespVO1 = randomPojo(ProductPropertyValueRespVO.class, o -> o.setPropertyId(v.getId()));
|
|
|
+ productPropertyValueRespVO.add(productPropertyValueRespVO1);
|
|
|
+ });
|
|
|
+
|
|
|
+ // 属性值建立笛卡尔积
|
|
|
+ Map<Long, List<ProductPropertyValueRespVO>> collect = productPropertyValueRespVO.stream().collect(Collectors.groupingBy(ProductPropertyValueRespVO::getPropertyId));
|
|
|
+ List<List<ProductPropertyValueRespVO>> lists = cartesianProduct(Lists.newArrayList(collect.values()));
|
|
|
+
|
|
|
+ // 准备sku参数
|
|
|
+ ArrayList<ProductSkuDO> productSkuDOS = Lists.newArrayList();
|
|
|
+ lists.forEach(pp -> {
|
|
|
+ List<ProductSkuDO.Property> property = pp.stream().map(ppv -> new ProductSkuDO.Property(ppv.getPropertyId(), ppv.getId())).collect(Collectors.toList());
|
|
|
+ ProductSkuDO productSkuDO = randomPojo(ProductSkuDO.class, o -> {
|
|
|
+ o.setProperties(property);
|
|
|
+ });
|
|
|
+ productSkuDOS.add(productSkuDO);
|
|
|
+
|
|
|
+ });
|
|
|
+
|
|
|
+ Mockito.when(productSkuService.getSkusBySpuId(createReqVO.getId())).thenReturn(productSkuDOS);
|
|
|
+ Mockito.when(productPropertyValueService.getPropertyValueListByPropertyId(new ArrayList<>(collect.keySet()))).thenReturn(productPropertyValueRespVO);
|
|
|
+ Mockito.when(productPropertyService.getPropertyList(new ArrayList<>(collect.keySet()))).thenReturn(productPropertyRespVOS);
|
|
|
+
|
|
|
+ // 调用
|
|
|
+ ProductSpuDetailRespVO spuDetail = productSpuService.getSpuDetail(createReqVO.getId());
|
|
|
+
|
|
|
+ assertPojoEquals(createReqVO, spuDetail);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ void getSpu() {
|
|
|
// 准备参数
|
|
|
- ProductSpuUpdateReqVO reqVO = randomPojo(ProductSpuUpdateReqVO.class);
|
|
|
+ ProductSpuDO createReqVO = randomPojo(ProductSpuDO.class);
|
|
|
+ productSpuMapper.insert(createReqVO);
|
|
|
|
|
|
- // 调用, 并断言异常
|
|
|
- assertServiceException(() -> spuService.updateSpu(reqVO), SPU_NOT_EXISTS);
|
|
|
+ ProductSpuRespVO spu = productSpuService.getSpu(createReqVO.getId());
|
|
|
+ assertPojoEquals(createReqVO, spu);
|
|
|
}
|
|
|
|
|
|
@Test
|
|
|
- public void testDeleteSpu_success() {
|
|
|
- // mock 数据
|
|
|
- ProductSpuDO dbSpu = randomPojo(ProductSpuDO.class);
|
|
|
- ProductSpuMapper.insert(dbSpu);// @Sql: 先插入出一条存在的数据
|
|
|
+ void getSpuList() {
|
|
|
// 准备参数
|
|
|
- Long id = dbSpu.getId();
|
|
|
+ ArrayList<ProductSpuDO> createReqVO = Lists.newArrayList(randomPojo(ProductSpuDO.class), randomPojo(ProductSpuDO.class));
|
|
|
+ productSpuMapper.insertBatch(createReqVO);
|
|
|
|
|
|
// 调用
|
|
|
- spuService.deleteSpu(id);
|
|
|
- // 校验数据不存在了
|
|
|
- assertNull(ProductSpuMapper.selectById(id));
|
|
|
+ List<ProductSpuDO> spuList = productSpuService.getSpuList(createReqVO.stream().map(ProductSpuDO::getId).collect(Collectors.toList()));
|
|
|
+ Assertions.assertIterableEquals(createReqVO, spuList);
|
|
|
}
|
|
|
|
|
|
@Test
|
|
|
- public void testDeleteSpu_notExists() {
|
|
|
+ void getSpuPage() {
|
|
|
// 准备参数
|
|
|
- Long id = 1L;
|
|
|
+ ProductSpuDO createReqVO = randomPojo(ProductSpuDO.class);
|
|
|
+ productSpuMapper.insert(createReqVO);
|
|
|
+
|
|
|
+ ArrayList<ProductSkuDO> remindSpuIds = Lists.newArrayList(
|
|
|
+// randomPojo(ProductSkuDO.class, o -> o.setSpuId(createReqVO.getId())),
|
|
|
+// randomPojo(ProductSkuDO.class, o -> o.setSpuId(createReqVO.getId()))
|
|
|
+ );
|
|
|
|
|
|
- // 调用, 并断言异常
|
|
|
- assertServiceException(() -> spuService.deleteSpu(id), SPU_NOT_EXISTS);
|
|
|
+ Mockito.when(productSkuService.getRemindSpuIds()).thenReturn(remindSpuIds);
|
|
|
+
|
|
|
+ // 调用
|
|
|
+ ProductSpuPageReqVO productSpuPageReqVO = new ProductSpuPageReqVO();
|
|
|
+ productSpuPageReqVO.setTabStatus(2);
|
|
|
+
|
|
|
+ PageResult<ProductSpuRespVO> spuPage = productSpuService.getSpuPage(productSpuPageReqVO);
|
|
|
+
|
|
|
+ ArrayList<Long> resultRemindSpuIds = new ArrayList<>();
|
|
|
+ resultRemindSpuIds.add(null);
|
|
|
+ PageResult<ProductSpuRespVO> result = ProductSpuConvert.INSTANCE.convertPage(productSpuMapper.selectPage(productSpuPageReqVO, resultRemindSpuIds));
|
|
|
+ Assertions.assertIterableEquals(result.getList(), spuPage.getList());
|
|
|
+ Assertions.assertEquals(spuPage.getTotal(), result.getTotal());
|
|
|
}
|
|
|
|
|
|
@Test
|
|
|
- @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解
|
|
|
- public void testGetSpuPage() {
|
|
|
- // mock 数据
|
|
|
- ProductSpuDO dbSpu = randomPojo(ProductSpuDO.class, o -> { // 等会查询到
|
|
|
- o.setName(null);
|
|
|
- o.setSellPoint(null);
|
|
|
- o.setDescription(null);
|
|
|
- o.setCategoryId(null);
|
|
|
- o.setPicUrls(null);
|
|
|
- o.setSort(null);
|
|
|
-// o.setLikeCount(null);
|
|
|
-// o.setPrice(null);
|
|
|
-// o.setQuantity(null);
|
|
|
- o.setStatus(null);
|
|
|
- o.setCreateTime(null);
|
|
|
- });
|
|
|
- ProductSpuMapper.insert(dbSpu);
|
|
|
- // 测试 name 不匹配
|
|
|
- ProductSpuMapper.insert(cloneIgnoreId(dbSpu, o -> o.setName(null)));
|
|
|
- // 测试 sellPoint 不匹配
|
|
|
- ProductSpuMapper.insert(cloneIgnoreId(dbSpu, o -> o.setSellPoint(null)));
|
|
|
- // 测试 description 不匹配
|
|
|
- ProductSpuMapper.insert(cloneIgnoreId(dbSpu, o -> o.setDescription(null)));
|
|
|
- // 测试 categoryId 不匹配
|
|
|
- ProductSpuMapper.insert(cloneIgnoreId(dbSpu, o -> o.setCategoryId(null)));
|
|
|
- // 测试 picUrls 不匹配
|
|
|
- ProductSpuMapper.insert(cloneIgnoreId(dbSpu, o -> o.setPicUrls(null)));
|
|
|
- // 测试 sort 不匹配
|
|
|
- ProductSpuMapper.insert(cloneIgnoreId(dbSpu, o -> o.setSort(null)));
|
|
|
- // 测试 likeCount 不匹配
|
|
|
-// ProductSpuMapper.insert(cloneIgnoreId(dbSpu, o -> o.setLikeCount(null)));
|
|
|
- // 测试 price 不匹配
|
|
|
-// ProductSpuMapper.insert(cloneIgnoreId(dbSpu, o -> o.setPrice(null)));
|
|
|
- // 测试 quantity 不匹配
|
|
|
-// ProductSpuMapper.insert(cloneIgnoreId(dbSpu, o -> o.setQuantity(null)));
|
|
|
- // 测试 status 不匹配
|
|
|
- ProductSpuMapper.insert(cloneIgnoreId(dbSpu, o -> o.setStatus(null)));
|
|
|
- // 测试 createTime 不匹配
|
|
|
- ProductSpuMapper.insert(cloneIgnoreId(dbSpu, o -> o.setCreateTime(null)));
|
|
|
- // 准备参数
|
|
|
- ProductSpuPageReqVO reqVO = new ProductSpuPageReqVO();
|
|
|
- reqVO.setName(null);
|
|
|
- reqVO.setSellPoint(null);
|
|
|
- reqVO.setDescription(null);
|
|
|
- reqVO.setCategoryId(null);
|
|
|
- reqVO.setPicUrls(null);
|
|
|
- reqVO.setSort(null);
|
|
|
- reqVO.setLikeCount(null);
|
|
|
- reqVO.setPrice(null);
|
|
|
- reqVO.setQuantity(null);
|
|
|
- reqVO.setStatus(null);
|
|
|
- reqVO.setCreateTime(null);
|
|
|
-
|
|
|
- // 调用
|
|
|
- PageResult<ProductSpuRespVO> pageResult = spuService.getSpuPage(reqVO);
|
|
|
- // 断言
|
|
|
- assertEquals(1, pageResult.getTotal());
|
|
|
- assertEquals(1, pageResult.getList().size());
|
|
|
- assertPojoEquals(dbSpu, pageResult.getList().get(0));
|
|
|
+ void testGetSpuPage() {
|
|
|
+// 准备参数
|
|
|
+ ProductSpuDO createReqVO = randomPojo(ProductSpuDO.class, o -> {
|
|
|
+ o.setCategoryId(2L);
|
|
|
+ });
|
|
|
+ productSpuMapper.insert(createReqVO);
|
|
|
+
|
|
|
+ ArrayList<ProductSkuDO> remindSpuIds = Lists.newArrayList(
|
|
|
+// randomPojo(ProductSkuDO.class, o -> o.setSpuId(createReqVO.getId())),
|
|
|
+// randomPojo(ProductSkuDO.class, o -> o.setSpuId(createReqVO.getId()))
|
|
|
+ );
|
|
|
+
|
|
|
+ Mockito.when(productSkuService.getRemindSpuIds()).thenReturn(remindSpuIds);
|
|
|
+
|
|
|
+ // 调用
|
|
|
+ AppSpuPageReqVO appSpuPageReqVO = new AppSpuPageReqVO();
|
|
|
+ appSpuPageReqVO.setCategoryId(2L);
|
|
|
+
|
|
|
+ PageResult<AppSpuPageRespVO> spuPage = productSpuService.getSpuPage(appSpuPageReqVO);
|
|
|
+
|
|
|
+ PageResult<ProductSpuDO> result = productSpuMapper.selectPage(
|
|
|
+ ProductSpuConvert.INSTANCE.convert(appSpuPageReqVO));
|
|
|
+
|
|
|
+ List<AppSpuPageRespVO> collect = result.getList()
|
|
|
+ .stream()
|
|
|
+ .map(ProductSpuConvert.INSTANCE::convertAppResp)
|
|
|
+ .collect(Collectors.toList());
|
|
|
+
|
|
|
+ Assertions.assertIterableEquals(collect, spuPage.getList());
|
|
|
+ Assertions.assertEquals(spuPage.getTotal(), result.getTotal());
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 生成笛卡尔积
|
|
|
+ *
|
|
|
+ * @param data 数据
|
|
|
+ * @return 笛卡尔积
|
|
|
+ */
|
|
|
+ public static <T> List<List<T>> cartesianProduct(List<List<T>> data) {
|
|
|
+ List<List<T>> res = null; // 结果集(当前为第N个List,则该处存放的就为前N-1个List的笛卡尔积集合)
|
|
|
+ for (List<T> list : data) { // 遍历数据
|
|
|
+ List<List<T>> temp = new ArrayList<>(); // 临时结果集,存放本次循环后生成的笛卡尔积集合
|
|
|
+ if (res == null) { // 结果集为null表示第一次循环既list为第一个List
|
|
|
+ for (T t : list) { // 便利第一个List
|
|
|
+ // 利用stream生成List,第一个List的笛卡尔积集合约等于自己本身(需要创建一个List并把对象添加到当中),存放到临时结果集
|
|
|
+ temp.add(Stream.of(t).collect(Collectors.toList()));
|
|
|
+ }
|
|
|
+ res = temp; // 将临时结果集赋值给结果集
|
|
|
+ continue; // 跳过本次循环
|
|
|
+ }
|
|
|
+ // 不为第一个List,计算前面的集合(笛卡尔积)和当前List的笛卡尔积集合
|
|
|
+ for (T t : list) { // 便利
|
|
|
+ for (List<T> rl : res) { // 便利前面的笛卡尔积集合
|
|
|
+ // 利用stream生成List
|
|
|
+ temp.add(Stream.concat(rl.stream(), Stream.of(t)).collect(Collectors.toList()));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ res = temp; // 将临时结果集赋值给结果集
|
|
|
+ }
|
|
|
+ // 返回结果
|
|
|
+ return res;
|
|
|
}
|
|
|
|
|
|
}
|