基本思路是执行以下步骤:
1)原始输入映射。
+
| Keys | Values |
+
| M1 | [A1, A3] |
+
| M2 | [A1, A2, A3] |
+
| M3 | [A1, A2] |
+
| M4 | [A2, A3] |
+
2) 以以下方式扩展映射。思路是将值分成子集,以便我们可以根据值对键进行分组。例如:[A1,A3]
在 M1
和 M2
中都存在,表示 [A1,A3]
在两个列表中都是共同的。
+
| Keys | Values | |
+
| M1 | [A1, A3] | |
+
| M2 | [A1, A2, A3] | Expanding this entry |
+
| M2 | [A1, A2] | of this key i.e. M2 with |
+
| M2 | [A1, A3] | combinations of the |
+
| M2 | [A2, A3] | |
+
| M3 | [A1, A2] | |
+
| M4 | [A2, A3] | |
+
3) 反转上述映射以便在新键上进行 groupBy 操作。
+
| Keys | Values |
+
| [A1, A3] | M1 |
+
| [A1, A2, A3] | M2 |
+
| [A1, A2] | M2 |
+
| [A1, A3] | M2 |
+
| [A2, A3] | M2 |
+
| [A1, A2] | M3 |
+
| [A2, A3] | M4 |
+
4) 一个以共同元素为键,对应键为其值的反转映射。
+
| Keys | Values |
+
| [A1, A3] | [M1,M2] |
+
| [A1, A2, A3] | [M2] |
+
| [A1, A2] | [M2,M3] |
+
| [A2, A3] | [M2,M4] |
+
代码:
然后以下代码会在第四步中创建上述提到的反向映射。
Map<List<Integer>, List<String>> invertedMap = inputMap.entrySet().stream()
.flatMap(test::getAllCombinationsOfAList)
.collect(Collectors.groupingBy(Entry::getKey,
Collectors.mapping(Entry::getValue, Collectors.toList())));
其中test::getAllCombinationsOfAList
是(使用{{link1:最多2^list_len次迭代}}):
static Stream<Entry<ArrayList<Integer>, String>> getAllCombinationsOfAList(Entry<String,List<Integer>> set)
{
int n = set.getValue().size();
Builder<Entry<ArrayList<Integer>,String>> entryStream = Stream.builder();
for (int i = 0; i < (1<<n); i++)
{
ArrayList<Integer> integers = new ArrayList<>();
for (int j = 0; j < n; j++) {
if ((i & (1 << j)) > 0)
integers.add(set.getValue().get(j));
}
if(integers.size() >=2 ) {
entryStream.accept(new AbstractMap.SimpleEntry<>(integers,set.getKey()));
}
}
return entryStream.build();
}
那么res.entrySet().forEach(System.out::println);
的输出结果是:
[1, 2, 3]=[M2]
[2, 3]=[M2, M4]
[1, 2]=[M2, M3]
[1, 3]=[M1, M2]
这里,key_list_length
表示匹配所需的最小公共元素数量。
value_list_length
>=2 表示确实存在匹配。
因此,key_list_length >= 2
和 value_list_length >= 2
是您期望的输出。例如:
Map<List<Integer>, List<String>> filteredMap = invertedMap.entrySet()
.stream()
.filter(e -> e.getKey().size() >=2 && e.getValue().size() >= 2)
.collect(Collectors.toMap(Entry::getKey,Entry::getValue));
filteredMap.entrySet().forEach(System.out::println);
输出:
[1, 2]=[M2, M3]
[2, 3]=[M2, M4]
[1, 3]=[M1, M2]