问题场景:
好比说一件商品有3中属性,每一个属性又有3种不一样的值,那么此时问,这几种属性可能的组合性,相信你很快就获得结果为"333=27"种,此时你能够实现的方式能够为三个for循环嵌套来实现,那么若是场景变了,若是是4种属性,那你可能就要4个for循环,那么若是此时又变成10个,那是否是要用10个循环了,此时的代码就显得笨重而且不易读,因此此时咱们就能够用递归实现此业务场景。**算法
解决思路:
一、能够将相同属性的值放到一个List中,规定一个List的子类,如ArrayList,将全部的相同属性值都放到一个ArrayList中去,此时有多少个属性就能够获得多少个封装了相同属性值的ArrayList。
二、将上述生成的全部的ArrayList都放到个List中,即List<ArrayList<?>>;
三、而后将上述List中的ArrayList顺序两个组合成一个新的LinkedList,此处新List子类型是为了和以前的ArrayList区分开来,以便后续区分对待。详见代码数组
代码示例:
public class MainTest { private static List returnList = new ArrayList(); public static void main(String[] args) { List<ArrayList<String>> stateLists = new ArrayList<ArrayList<String>>(); ArrayList<String> als1 = new ArrayList<>(); als1.add("Color_1"); als1.add("Color_2"); ArrayList<String> als2 = new ArrayList<>(); als2.add("Style_1"); als2.add("Style_2"); ArrayList<String> als3 = new ArrayList<>(); als3.add("Size_1"); als3.add("Size_2"); ArrayList<String> als4 = new ArrayList<>(); als4.add("High_1"); als4.add("High_2"); stateLists.add(als1); stateLists.add(als2); stateLists.add(als3); stateLists.add(als4); addstatement(stateLists); System.out.println("returnList:"+returnList.size()+" "+returnList); } public static void addstatement(List<?> dataLists){ int len=dataLists.size(); //判断List中的size是否小于2,若是小于说明已经递归完成了 if (len<2){ returnList=dataLists; return; } //第一个是 ArrayList 或 LinkedList() int len0 ; if(dataLists.get(0) instanceof ArrayList<?>){ len0 = ((ArrayList<String>)dataLists.get(0)).size(); } else { len0 = ((LinkedList<String>)dataLists.get(0)).size(); } int len1 ; //第二个必定是 ArrayList ArrayList<String> secondList = (ArrayList<String>)dataLists.get(1); len1 = ((ArrayList<String>)dataLists.get(1)).size(); //定义临时存放排列数据的集合默认的是ArrayList,新组合的是 LinkedList LinkedList<LinkedList<String>> tempdataLists=new LinkedList<>(); //第一层for就是循环dataLists第一个元素的 for (int i=0;i<len0;i++){ //第二层for就是循环dataLists第二个元素的 for (int j=0;j<len1;j++){ //判断第一个元素若是是ArrayList说明循环才刚开始 if (dataLists.get(0) instanceof ArrayList<?>){ ArrayList<String> arr0= (ArrayList<String>) dataLists.get(0); // 建立LinkedList类型与ArrayList区分开来,用于将新的数据从新存储 LinkedList<String> arr=new LinkedList<>(); arr.add(arr0.get(i)); arr.add(secondList.get(j)); //把排列数据加到临时的集合中 tempdataLists.add(arr); } else { //到这里就明循环了最少一轮,即数据中只剩下两个,一个是LinkedList,一个是ArrayList LinkedList<LinkedList<String>> arrtemp= (LinkedList<LinkedList<String>>) dataLists.get(0); LinkedList<String> arr=new LinkedList<>(); // 取出老的LinkedList数据赋值给新的LinkedList,同时把第二个ArrayList中的数据赋值给新的LinkedList for (int k=0;k<arrtemp.get(i).size();k++){ arr.add(arrtemp.get(i).get(k)); } arr.add(secondList.get(j)); tempdataLists.add(arr); } } } //这是根据上面排列的结果从新生成的一个集合 List newdataLists=new ArrayList<>(); //把还没排列的数组装进来,看清楚i=2的喔,由于前面两个数组已经完事了,不须要再加进来了 for (int i=2;i<dataLists.size();i++){ newdataLists.add(dataLists.get(i)); } //记得把咱们辛苦排列的数据加到新集合的第一位喔,否则白忙了 newdataLists.add(0,tempdataLists); //你没看错,咱们这整个算法用到的就是递归的思想。 addstatement(newdataLists); } }
运行结果:
returnList:1 [[[Color_1, Style_1, Size_1, High_1], [Color_1, Style_1, Size_1, High_2], [Color_1, Style_1, Size_2, High_1], [Color_1, Style_1, Size_2, High_2], [Color_1, Style_2, Size_1, High_1], [Color_1, Style_2, Size_1, High_2], [Color_1, Style_2, Size_2, High_1], [Color_1, Style_2, Size_2, High_2], [Color_2, Style_1, Size_1, High_1], [Color_2, Style_1, Size_1, High_2], [Color_2, Style_1, Size_2, High_1], [Color_2, Style_1, Size_2, High_2], [Color_2, Style_2, Size_1, High_1], [Color_2, Style_2, Size_1, High_2], [Color_2, Style_2, Size_2, High_1], [Color_2, Style_2, Size_2, High_2]]]code