关于对象集合计算笛卡尔积

集合对象获取笛卡尔积

实际业务场景说明

应用:根据导入的属性名称以及属性值(两者都为“/”划分的字符串),基于属性及属性值组合生成所有的商品规格(规格值组合);需要补全导入文件中未填入的数据。
本人作为记录和大家学习使用。
数据示例:
属性名称1:属性值1-1,属性值1-2,属性值1-3
属性名称2:属性值2-1,属性值2-2,属性值2-3
结果:理论可得组合应为3*3=9种;
由于本人使用的环境版本较低,无法直接使用高版本自带的笛卡尔积获取方法;故问度娘后,抄了一位大佬的方法,实测可行。

实现

最容易想到的就是递归。

递归

介绍:对程序语言来说,递归就是间接或者直接调用自身的一种方法。

 /**
     * 递归实现
     * 原理:从原始list的0开始依次遍历到最后
     *
     * @param originalList 原始list 
     * @param position     当前递归在原始list的position 起始为0
     * @param returnList   返回结果 
     * @param cacheList    临时保存的list 
     */
    private static <T> void descartesRecursive(List<List<T>> originalList, int position, List<List<T>> returnList, List<T> cacheList) {
        List<T> originalItemList = originalList.get(position);
        for (int i = 0; i < originalItemList.size(); i++) {
            //最后一个复用cacheList,节省内存
            List<T> childCacheList = (i == originalItemList.size() - 1) ? cacheList : new ArrayList<>(cacheList);
            childCacheList.add(originalItemList.get(i));
            if (position == originalList.size() - 1) {//遍历到最后退出递归
                returnList.add(childCacheList);
                continue;
            }
            descartesRecursive(originalList, position + 1, returnList, childCacheList);
        }
    }

经过大佬改良的代码,如下:
其实就是省去了传参,使用了stream的集合合并

private static <T> List<List<T>> descartesRecursive(List<List<T>> originalList) {
        List<List<T>> data = new ArrayList<>();
        for (List<T> list : originalList) {
            List<List<T>> temp = new ArrayList<>();
            if(CollectionUtils.isEmpty(data)){
                for(T t : list){
                    temp.add(Stream.of(t).collect(Collectors.toList()));
                }
                data = temp;
                continue;
            }
            for(T t : list){
                for (List<T> re : data) {
                    temp.add(Stream.concat(re.stream(), Stream.of(t)).collect(Collectors.toList()));
                }
            }
            data = temp;
        }
        return data;
    }

基于guava工具包的解法
缺点是已知集合数量,没研究,不知道有没有不确定集合数的。

List<List<String>> cartesianProductList = Lists.cartesianProduct(Lists.newArrayList("A", "B", "C"), Lists.newArrayList("a1", "b1", "c1"));

因为数据在组装后需要根据名称进行Id绑定,所以数据结构其实是是双层的集合List<List>。
问题:实际上这种应用场景在真实需求中非常鸡肋,因为会极大增加系统的负担,
本人也是在拿到生产数据后测试得知,因为笛卡尔积这一需求,对导入文件的数据限制失去意义,因为属性及属性值的增加会导致笛卡尔积结果的成倍增加。可能20条导入数据就能产生几百种组合对应的写入数据。

最后,方法网上找的,不是本人原创,侵联删

最后,整几篇过程中研究过的帖子,没看懂,用了stream,大家可以看看:
https://www.codenong.com/38623759/

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值