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

本文介绍了如何在低版本环境下实现集合对象的笛卡尔积,通过递归和流式处理两种方式,并讨论了在商品规格生成中的应用。由于属性值的增加会导致组合爆炸性增长,这种方法在实际需求中可能存在效率问题。同时,文章提供了Guava工具包的解决方案,但受限于已知集合数量。最后,探讨了数据结构选择和导入数据的限制对系统性能的影响。
摘要由CSDN通过智能技术生成

集合对象获取笛卡尔积

实际业务场景说明

应用:根据导入的属性名称以及属性值(两者都为“/”划分的字符串),基于属性及属性值组合生成所有的商品规格(规格值组合);需要补全导入文件中未填入的数据。
本人作为记录和大家学习使用。
数据示例:
属性名称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、付费专栏及课程。

余额充值