n阶for循环代码实现

本文探讨了如何在Java中实现n层for循环,以满足动态词包组合生成的需求。介绍了两种方法:一是通过递归将n阶循环转化为2层for循环;二是使用双数组,如同时针和分针,从最大值开始逐步减少组合。
背景

业务需求需要图片根据DMP多个类型动态词包内容生成n*n的所有组合图片,这就需要先组合出所有词包的可能,且词包类型数量不限制,总组合数可以控制。本文重点记录n层for循环java代码实现。

实现1: for循环递归

通过递归方式,把n阶循环转变到2层for循环

@Test
public void recursionFor() {
    Map<Integer, Set<Long>> map = new HashMap<>();
    Long[] l1 = {1L, 2L};
    Long[] l2 = {3L, 4L,5L};
    Long[] l3 = {6L, 7L};
    map.put(1, new HashSet<>(Arrays.asList(l1)));
    map.put(2, new HashSet<>(Arrays.asList(l2)));
    map.put(3, new HashSet<>(Arrays.asList(l3)));
    List<Map<Integer, Long>> xx = getAllTagTypeAndTagIdMatch(map);
    System.out.println(xx);
}
/**
 *  递归获取所有的组合
 * @param tagTypeTagIdMap key为词包类型,value为词包内容集合
 * @return 按词包类型返回所有的组合内容
 */
private List<Map<Integer, Long>> getAllTagTypeAndTagIdMatch(Map<Integer, Set<Long>> tagTypeTagIdMap){

    if (tagTypeTagIdMap.size() == 1) {
        List<Map<Integer, Long>> result = new ArrayList<>();
        for (Map.Entry<Integer, Set<Long>> entry : tagTypeTagIdMap.entrySet()) {
            for (Long tagID : entry.getValue()) {
                Map<Integer, Long> map = new HashMap<>();
                map.put(entry.getKey(), tagID);
                result.add(map);
            }
        }
        return result;
    } else if (tagTypeTagIdMap.size() == 2) {
        Set<Integer> tagTypeSet = tagTypeTagIdMap.keySet();
        Iterator<Integer> iterator = tagTypeSet.iterator();
        Integer tagType1 = iterator.next();
        Integer tagType2 = iterator.next();
        Set<Long> tagIdSet1 = tagTypeTagIdMap.get(tagType1);
        Set<Long> tagIdSet2 = tagTypeTagIdMap.get(tagType2);

        List<Map<Integer, Long>> result = new ArrayList<>();
        for (Long tagId1 : tagIdSet1) {
            for (Long tagId2 : tagIdSet2) {
                Map<Integer, Long> map = new HashMap<>();
                map.put(tagType1, tagId1);
                map.put(tagType2, tagId2);
                result.add(map);
            }
        }
        return result;
    } else {

        List<Map<Integer, Long>> result = new ArrayList<>();

        Set<Integer> tagTypeSet = tagTypeTagIdMap.keySet();
        Iterator<Integer> iterator = tagTypeSet.iterator();

        if (iterator.hasNext()) {
            Integer tagType1 = iterator.next();
            Set<Long> tagIdSet = tagTypeTagIdMap.get(tagType1);
            Map<Integer, Set<Long>> newTagTypeTagIdMap = new HashMap<>();
            newTagTypeTagIdMap.putAll(tagTypeTagIdMap);
            newTagTypeTagIdMap.remove(tagType1);
            List<Map<Integer, Long>> oneResult = getAllTagTypeAndTagIdMatch(newTagTypeTagIdMap);
            for (Map<Integer, Long> oneMap : oneResult) {
                for (Long tagId : tagIdSet) {
                    Map<Integer, Long> map = new HashMap<>();
                    map.putAll(oneMap);
                    map.put(tagType1, tagId);
                    result.add(map);
                }
            }
        }
        return result;
    }
}
实现2 双数组

双数组记录每层数(即每个词包类型的内容数),类似时分秒指针,从词包最大内容值和最外层一点点减小组合。

@Test
public void doubleArrayFor() {
    Map<Integer, List<Long>> map = new HashMap<>();
    Long[] l1 = {1L, 2L};
    Long[] l2 = {3L, 4L, 5L};
    Long[] l3 = {6L};
    map.put(1, Arrays.asList(l1));
    map.put(2, Arrays.asList(l2));
    map.put(3, Arrays.asList(l3));
    List<Map<Integer, List<Long>>> xx = createAllCombination(map);
    System.out.println(xx);
}

/**
 * 生成所有组合
 * @param dmpTagTypeMap
 * @return
 */
public List<Map<Integer, List<Long>>> createAllCombination(Map<Integer, List<Long>> dmpTagTypeMap) {
    List<Map<Integer, List<Long>>> resultList = new ArrayList<>();
    int size = dmpTagTypeMap.size();
    if(size <= 0){
        return resultList;
    }
    int[] tree0 = new int[size];
    int[] tree1 = new int[size];
    int i = 0;
    for (Integer dmpTagType : dmpTagTypeMap.keySet()) {
        List<Long> longList = dmpTagTypeMap.get(dmpTagType);
        tree0[i] = longList.size()-1;
        tree1[i] = longList.size()-1;
        i++;
    }
    while (tree0[0] >= 0) {
        Map<Integer, List<Long>> result = new HashMap<>(size);
        int j = 0;
        for (Integer dmpTagType : dmpTagTypeMap.keySet()) {
            List value = dmpTagTypeMap.get(dmpTagType);
            Long lv = (Long) value.get(tree0[j]);
            result.put(dmpTagType,Arrays.asList(lv));
            j++;
        }
        resultList.add(result);
        subTree(tree0,tree1,size-1);
    }
    return resultList;
}
/**
 * 确定每次组合取值范围,当最外层遍历到<0时,恢复这层原始值,开始衰减倒数第二层数
 * @param tree0 当前每层取值范围,会一直变更
 * @param tree1 记录最原始每层数据
 * @param subIndex 当前层偏移值
 */
private static void subTree(int[] tree0,int[] tree1,int subIndex){
    if (subIndex>0){
        if (--tree0[subIndex]<0) {
            tree0[subIndex] = tree1[subIndex];
            subTree(tree0, tree1, --subIndex);
        }
    }else if (subIndex == 0) --tree0[0];
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值