排列组合:将实体的属性设置重组

需求描述:
根据给定的每个字段的所有值进行排列组合得到一个唯一条件的实体对象。
比如:

Model中有A\B\C三个字段:

  • A字段可能的值是1,2,3
  • B字段可能的值是4,5,6
  • C字段可能的值是1,2,5

这个时候需要根据ABC三个字段的值进行重组,得到一个唯一属性的Model。

比如:

  • Model1 : A -> 1,B->4,C->1
  • Model2 : A -> 1,B->4,C->2
  • Model3 : A -> 1,B->4,C->5
  • Model4 : A -> 1,B->5,C->1

得到所有的可能性…

import org.apache.commons.beanutils.BeanUtils;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;

public class ZhiShuUtils {

   /**
    * 构建对象
    *
    * @param ruleMap 规则参数
    * @param clazz   转换结果
    * @param <T>
    * @return
    * @throws Exception
    */
   public static <T> List<T> builderObject(Map<String, Object> ruleMap, Class<T> clazz) throws Exception {
       // 先将Map中的数组大小相乘,得到最终的总条数
       Integer maxListSize = 1;
       for (Object value : ruleMap.values()) {
           if (value instanceof Collection) {
               int size = ((Collection)value).size();
               maxListSize = maxListSize * size;
           }
       }

       List<Map.Entry<String, Object>> list = new ArrayList<Map.Entry<String, Object>>(ruleMap.entrySet());

       // 提前构建参数可能性的对象总数
       List<Object> resultMap = new ArrayList<>(maxListSize);

       for (int i = 0; i < maxListSize; i++) {
           resultMap.add(clazz.newInstance());
       }

       //迭代
       int iterationCount = 1;

       for (int i = 0; i < list.size(); i++) {
           Map.Entry<String, Object> map = list.get(i);
           if (i > 0) {
               Map.Entry<String, Object> preMap = list.get(i - 1);
               if (preMap.getValue() instanceof List) {
                   iterationCount = iterationCount * ((List<?>)preMap.getValue()).size();
               }
           }
           putAttr(map.getKey(), map.getValue(), resultMap, iterationCount);
       }

       return (List<T>)resultMap;
   }

   /**
    * 设置属性
    *
    * @param key         字段名称
    * @param value       字段值
    * @param resultMap   实体对象集合
    * @param resultIndex 结果下标
    */
   private static void putAttr(String key, Object value, List<Object> resultMap, Integer resultIndex) {
       int resultSize = resultMap.size();
       if (value instanceof List) {
           List valueObject = (List)value;
           int valueSize = valueObject.size();
           for (int i = 0; i < resultSize; i++) {
               Object object = resultMap.get(i);
               int index = i / resultIndex % valueSize;
               Object val = valueObject.get(index);
               setProperty(object, key, val);
           }
       } else {
           allEachValue(key, value, resultMap, resultSize);
       }
   }

   /**
    * 遍历所有的参数值
    *
    * @param key
    * @param value
    * @param resultMap
    * @param resultSize
    */
   private static void allEachValue(String key, Object value, List<Object> resultMap, int resultSize) {
       for (int i = 0; i < resultSize; i++) {
           Object object = resultMap.get(i);
           setProperty(object, key, value);
       }
   }

   /**
    * 设置属性
    *
    * @param object
    * @param key
    * @param value
    */
   private static void setProperty(Object object, String key, Object value) {
       try {
           BeanUtils.setProperty(object, key, value);
       } catch (Exception e) {
           System.out.println(e.getMessage());
       }
   }
}

调用和验证方式:


@Test
public void test() throws Exception {
	// 这里的map的key属性和TestModel中字段需要对应
    Map<String, Object> ruleMap = new LinkedHashMap<>();
    ruleMap.put("a", Arrays.asList("1", "2", "3"));
    ruleMap.put("b", Arrays.asList("4", "5", "6"));
    ruleMap.put("c", Arrays.asList("1", "2", "5"));
    List<TestModel> ruleList = ZhiShuUtils.builderObject(ruleMap, TestModel.class);

    Set<TestModel> arraySet = new HashSet<>();
    ruleList.forEach((model) -> {
        if (!arraySet.add(model)) {
            System.out.println("---->>>存在重复 : " + model);
        }
        System.out.println(model);
    });
}

结果:

TestModel{a='1', b='4', c='1'}
TestModel{a='2', b='4', c='1'}
TestModel{a='3', b='4', c='1'}
TestModel{a='1', b='5', c='1'}
TestModel{a='2', b='5', c='1'}
TestModel{a='3', b='5', c='1'}
TestModel{a='1', b='6', c='1'}
TestModel{a='2', b='6', c='1'}
TestModel{a='3', b='6', c='1'}
TestModel{a='1', b='4', c='2'}
TestModel{a='2', b='4', c='2'}
TestModel{a='3', b='4', c='2'}
TestModel{a='1', b='5', c='2'}
TestModel{a='2', b='5', c='2'}
TestModel{a='3', b='5', c='2'}
TestModel{a='1', b='6', c='2'}
TestModel{a='2', b='6', c='2'}
TestModel{a='3', b='6', c='2'}
TestModel{a='1', b='4', c='5'}
TestModel{a='2', b='4', c='5'}
TestModel{a='3', b='4', c='5'}
TestModel{a='1', b='5', c='5'}
TestModel{a='2', b='5', c='5'}
TestModel{a='3', b='5', c='5'}
TestModel{a='1', b='6', c='5'}
TestModel{a='2', b='6', c='5'}
TestModel{a='3', b='6', c='5'}

具体思路:

  1. 遍历规则中的每个参数长度大小,得到组合结果总数的长度;
  2. 提前初始化所有结果对象
  3. 遍历规则Map中的每个属性填充到结果对象中.

其中第一次遍历的时候是按照顺序循环遍历,后面的话根据上一次的总数累计相乘得到每个值遍历的次数进行循环遍历,有点绕,不过你看打印结果就能够理解了。

也花了蛮多时间,觉得有意思,分享给有需要的人。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值