是否有可能将一个Java Map<Integer, Integer> m0转换为一个新的Map<Integer, List<Integer>> m1,其中m1映射中的键作为m0映射的值,而值作为m0映射的键的List<Integer>?
换句话说,这个任务是关于转换按值分组的键值对的。
我尝试了以下几点:
public static void main(String[] args) {
Map<Integer, Integer> m = new HashMap<>();
m.put(1, 1);
m.put(2, 1);
m.put(3, 1);
m.put(4, 2);
m.put(5, 2);
m.put(6, 2);
m.put(7, 2);
Map<Integer, List<Integer>> personByAge
= m.values()
.stream()
.collect(Collectors.groupingBy(Function.identity(), Collectors.toList()));
Iterator it = personByAge.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<Integer, List<Integer>> me = (Map.Entry)it.next();
System.out.println(me.getKey() + " <- key" );
for (int i : me.getValue())
{
System.out.println("Values: " + i);
}
}
}但是第二张地图中的值是错误的。
这些价值应该是:
1 <- key Values: 1 Values: 2 Values: 3
2 <- key Values: 4 Values: 5 Values: 6 Values: 7但我得到了:
1 <- key Values: 1 Values: 1 Values: 1
2 <- key Values: 2 Values: 2 Values: 2 Values: 2发布于 2022-07-04 06:43:50
它是关于按值分组的键值对的反转。
如果要像注释中所说的那样反转map,则需要在源映射的条目上创建流,而不是在值上创建流:
Map<Integer, List<Integer>> personByAge = m.entrySet()
.stream()
.collect(Collectors.groupingBy(
Map.Entry::getValue,
Collectors.mapping(Map.Entry::getKey,
Collectors.toList())));
personByAge.forEach((k, v) -> System.out.println(k + " -> " + v));输出:
1 -> [1, 2, 3]
2 -> [4, 5, 6, 7]发布于 2022-07-04 06:42:29
Map<Integer, List<Integer>> personByAge
= m.entrySet()
.stream()
.collect(Collectors.groupingBy(
Map.Entry::getValue,
Collectors.mapping(
Map.Entry::getKey,
Collectors.toList())));发布于 2022-07-04 07:08:14
下面的工作将使用forEach和computeIfAbsent
Map<Integer, List<Integer>> personByAge = new HashMap<>();
m.forEach((k, v) -> personByAge.computeIfAbsent(v, ArrayList::new).add(k));对多个类型使用Set可能更好,因为在迭代Map时没有顺序保证,而且键已经是唯一的。
这实际上是实现了flip的等效,它包含在MutableMap上的日食收藏中。区别在于flip返回一个MutableSetMultimap。下面是一个使用flip的示例。
MutableMap<Integer, Integer> m = Maps.mutable.empty();
m.put(1, 1);
m.put(2, 1);
m.put(3, 1);
m.put(4, 2);
m.put(5, 2);
m.put(6, 2);
m.put(7, 2);
MutableSetMultimap<Integer, Integer> personByAge = m.flip();
System.out.println(personByAge);输出:
{1=[1, 2, 3], 2=[4, 5, 6, 7]}因为flip返回一个SetMultimap,所以编写测试断言更容易,因为顺序在多个值上不重要。例如。可以为此示例编写以下测试。
SetMultimap<Integer, Integer> personByAge = m.flip();
SetMultimap<Integer, Integer> expected =
Multimaps.mutable.set.<Integer, Integer>empty()
.withKeyMultiValues(1, 3, 2, 1)
.withKeyMultiValues(2, 7, 5, 6, 4);
Assertions.assertEquals(expected, personByAge);如果您的源代码是一个JDK HashMap,并且您希望使用流,下面的代码将使用来自Eclipse的Collectors2实现等效的flip。
SetMultimap<Integer, Integer> personByAge = m.entrySet().stream()
.collect(Collectors2.toSetMultimap(Map.Entry::getValue, Map.Entry::getKey));
SetMultimap<Integer, Integer> expected =
Multimaps.mutable.set.<Integer, Integer>empty()
.withKeyMultiValues(1, 3, 2, 1)
.withKeyMultiValues(2, 7, 5, 6, 4);
Assertions.assertEquals(expected, personByAge);注意:我是Eclipse集合的提交者。
https://stackoverflow.com/questions/72852419
复制相似问题