我有LinkedHashMap
的{{1}}。我正在构建地图,因此也许有更好的方法来组织所有数据。
我正在尝试获取具有公共列表的键,每个列表中至少有2个相同的元素。
例如:
<String, List<T>>
最后,我希望有以下列表:Map
----------------------
| Key | Values |
----------------------
| M1 | [A1, A3] |
| M2 | [A1, A2, A3] |
| M3 | [A1, A2] |
| M4 | [A2, A3] |
----------------------
我一直在努力弄清楚如何将我的第一个条目的值与所有其他条目的值进行比较。依此类推,直到到达地图的末尾(如列表的双[ [M2, M3], [M2, M4], [M1, M2] ]
循环)。
我现在的解决方案(但我绝对觉得有更好的方法)
for
正在使用地图吗?
性能暂时不是问题。但是,获得平滑的效果总是更好的选择
答案 0 :(得分:0)
您可以使用以下方法
1)迭代映射中每个键的值(将是一个列表)
2)从上述迭代的下一个索引开始另一个迭代,直到结束
3)对于#1列表中的每个元素,请使用contains方法检查其是否在#2列表中
a) Finish iterating list #3 as soon as two identical objects are found
b) Iterate list in #3 till last but one if no element one
c) Iterate list in #3 till last if one element found
希望对您有帮助
答案 1 :(得分:0)
您在这里。我用String代替Generic:
static Set<String> getCommonKeySet() {
Map<String, List<String>> map = new HashMap<>();
Set<String> listOfKeysWithCommonValueSet = new HashSet<>();
map.forEach((key, value) -> {
map.entrySet().forEach(entry1 -> {
List<String> list = new ArrayList<>(value);
List<String> list1 = new ArrayList<>(entry1.getValue());
list.retainAll(list1);
if (list.size() >= 2)
listOfKeysWithCommonValueSet.add(key);
});
});
return listOfKeysWithCommonValueSet;
}
编辑:
要返回Set<Set<String>>
,请使用以下代码:
static Set<Set<String>> getCommonKeySet() {
Map<String, List<String>> map = new LinkedHashMap<>();
map.put("M1", Arrays.asList("A1", "A3"));
map.put("M2", Arrays.asList("A1", "A2", "A3"));
map.put("M3", Arrays.asList("A1", "A2"));
map.put("M4", Arrays.asList("A2", "A3"));
//Map<String, List<String>> map = new HashMap<>();
Set<Set<String>> listOfKeysWithCommonValueSet = new HashSet<>();
map.forEach((key, value) -> {
map.entrySet().forEach(entry1 -> {
if(!entry1.getKey().equals(key))
{
List<String> list = new ArrayList<>(value);
List<String> list1 = new ArrayList<>(entry1.getValue());
list.retainAll(list1);
if (list.size() >= 2)
{
Set<String> set = new HashSet<>();
set.add(key);
set.add(entry1.getKey());
listOfKeysWithCommonValueSet.add(set);
}
}
});
});
System.out.println(listOfKeysWithCommonValueSet);
return listOfKeysWithCommonValueSet;
}
输出:
[[M1,M2],[M2,M3],[M2,M4]]
答案 2 :(得分:0)
正如我所注意到的,您需要List<List<Output>>
,它对应于结构[ [M2, M3], [M2, M4], [M1, M2] ]
。
考虑非常相同的输入:
Map<String, List<String>> map = new LinkedHashMap<>();
map.put("M1", Arrays.asList("A1", "A3"));
map.put("M2", Arrays.asList("A1", "A2", "A3"));
map.put("M3", Arrays.asList("A1", "A2"));
map.put("M4", Arrays.asList("A2", "A3"));
这是可行的解决方案:
List<List<String>> output = new ArrayList<>(); // The output List
Set<String> keys = new HashSet<>(); // Key storage used to avoid comparison
// of the keys twice (M1-M2, M2-M1)
for (Entry<String, List<String>> entryOuter: map.entrySet()) { // First iteration
if (keys.add(entryOuter.getKey())) { // Adds a new key
for (Entry<String, List<String>> entryInner: map.entrySet()) { // Second iteration
if (!keys.contains(entryInner.getKey())) { // To compare?
List<String> common = new ArrayList<>(entryOuter.getValue());
common.retainAll(new ArrayList<>(entryInner.getValue())); // The common items
if (common.size() > 1) { // At least 2 common?
output.add(Arrays.asList{
entryOuter.getKey(), entryInner.getKey())); // Add these keys
}
}
}
}
}
调用System.out.println(output);
将显示所需的结果:
[[M1,M2],[M2,M3],[M2,M4]]
简要地描述了这个想法:
Set<String> keys
存储“已选中”键。List
中。您已经标记了java-8,所以我建议您可能要使用java-stream,这在这里没有真正的好处。除非您实施变通方法,否则linkedhashmap不会帮助您轻松地使用索引进行迭代:How get value from LinkedHashMap based on index not on key?
答案 3 :(得分:0)
基本思路是执行以下步骤:
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 |
+------+--------------+ to create a mapping +
| M2 | [A1, A2] | of this key i.e. M2 with |
+------+--------------+ all the possible +
| M2 | [A1, A3] | combinations of the |
+------+--------------+ original value [A1, A2, A3] +
| 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] |
+--------------+---------+
代码:
然后,下面的代码在第4步中创建上述倒置地图。
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
是(带有max 2^list_len iterations):
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]
答案 4 :(得分:0)
使用Map<String, Set<T>>
而不是List
。然后您自己的算法就可以发挥作用了。
Set<T> common = new HashSet<>(valuesA);
common.retainAll(valuesB);
if (common.size() > 1) ...
列表将可用于地图,甚至可以用于common
,但效率较低,不太适用。