Map <object,list <object =“”>&gt;的组合

时间:2017-06-06 13:07:10

标签: java hashmap combinations

我有HashMap<GC, List<RR>>样本数据,如:

key   values

gc1 - rr1
    - rr2
    - rr3

gc2 - rr4
    - rr5

gc3 - rr6

我需要从不同的GC创建所有可能的RR组合,如:

Combination1: rr1, rr4, rr6
Combination2: rr1, rr5, rr6
Combination3: rr2, rr4, rr6
Combination4: rr2, rr5, rr6
Combination5: rr3, rr4, rr6
Combination6: rr3, rr5, rr6

到目前为止,我已经尝试过,正如@Sanket Makani建议的那样,将我的HashMap<GC, List<RR>>转换为List<List<RR>>,然后遍历所有元素,如:

List<List<RR>> inputList = new ArrayList<List<RR>>();

for (Map.Entry<GC, List<RR>> rrList : Map.entrySet()) {
    inputList.add(rrList.getValue());
}

List<List<RR>> combinationsList = new ArrayList<List<RR>>();

for (List<RR> rrList : inputList) {
    List<RR> rrList1 = new ArrayList<RR>();
    for (RR rr : rrList) {
        rrList1.add(rr);
    }
    combinationsList.add(rrList1);
}

这对我不起作用,因为它将一个GC中的所有RR分组为:

Combination1: rr1, rr2, rr3
Combination2: rr4, rr5
Combination3: rr6

所以我的问题是,我如何调整我的代码以获得预期的结果?

PS:遗憾的是我正在使用Java6,因此不允许使用lambdas / stream。

PS2:我见过类似的问题,但找不到我想要的确切示例。

编辑:

这是我在@nandsito的回答中的最终实现:

//this method groups RRs by GC key with a given list
HashMap<GC, List<RR>> GCRRHashMap = groupRRsByGC(list); 

List<Map.Entry<GC, List<RR>>> mapEntryList = new ArrayList<Map.Entry<GC, List<RR>>>(GCRRHashMap.entrySet());
List<List<RR>> combinationsList = new ArrayList<List<RR>>();
List<RR> combinations = new ArrayList<RR>();

generateCombinations(mapEntryList, combinations, combinationsList);



private void generateCombinations(
  List<Map.Entry<GC, List<RR>>> mapEntryList, 
  List<RR> combinations, List<List<RR>> combinationsList) {

  if (mapEntryList.isEmpty()) {
    combinationsList.add(new ArrayList<RoomStay>(combinations)); 
    return;
  }

  Map.Entry<GC, List<RR>> entry = mapEntryList.remove(0);

  List<RR> entryValue = new ArrayList<RR>(entry.getValue());

  while (!entryValue.isEmpty()) {

    RR rr = entryValue.remove(0);

    combinations.add(rr);

    generateCombinations(mapEntryList, combinations, combinationsList);

    combinations.remove(combinations.size() - 1);
  }

  mapEntryList.add(0, entry);

}

2 个答案:

答案 0 :(得分:2)

这是一个递归解决方案:

public static void main(String[] args) {

    // your data map
    Map<GC, List<RR>> map;

    // the map entry set as list, which will help
    // combining the elements
    //
    // note this is a modifiable list

    List<Map.Entry<GC, List<RR>>> mapEntryList =
            new ArrayList<Map.Entry<GC, List<RR>>>(map.entrySet());

    // the combinations list, which will store
    // the desired results

    List<RR> combinations = new ArrayList<RR>();

    doRecursion(mapEntryList, combinations);
}

private static void doRecursion(
        List<Map.Entry<GC, List<RR>>> mapEntryList,
        List<RR> combinations) {

    // end of recursion

    if (mapEntryList.isEmpty()) {

        // do what you wish
        //
        // here i print each element of the combination

        for (RR rr : combinations) {

            System.out.println(rr);
        }

        System.out.println();

        return;
    }

    // remove one GC from the entry list,
    // then for each RR from the taken GC
    //     put RR in the combinations list,
    //     call recursion
    //     the remove RR from the combinations list
    // end for each
    // then put GC back into its list

    Map.Entry<GC, List<RR>> entry = mapEntryList.remove(0);

    List<RR> entryValue = new ArrayList<RR>(entry.getValue());

    while (!entryValue.isEmpty()) {

        RR rr = entryValue.remove(0);

        combinations.add(rr);

        doRecursion(mapEntryList, combinations);

        combinations.remove(combinations.size() - 1);
    }

    mapEntryList.add(0, entry);
}

答案 1 :(得分:1)

您真正需要做的就是通过递增索引列表:

0,0,0
0,1,0
1,0,0
1,1,0
2,0,0
... etc.

如何将每个行转换为数据结构中的值应该是显而易见的。例如0,0,0映射到rr1, rr4, rr6。这将涉及将地图转换为列表,以使索引保持一致。

它非常类似于正常的base-b计数,你增加最右边的列,如果它溢出,设置为零并递增下一列。唯一的区别是每列溢出的数字不同。

所以:

boolean increment(int[] indexes) {
   int column = 0;
   while(true) {
      indexes[column]++;
      if(indexes[column] <  numberOfRRsInColumn(column)) {
         return true;  // finished
      }
      indexes[column]=0;
      column++;
      if(column = indexes.length) {
         return false; // can't increment, no more.
      }
   }
}

此实现使用indexes[0]作为“最右侧”列。我已经掩饰了numberOfRRsInColumn(),但是如何做到这一点应该非常明显。

然后:

int[] indexes = new int[mapsize];
do {
    output(translate(map, indexes));
} while (increment(indexes));