首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用流将Map<Integer、Integer>转换为Map<key,list<Integer>>

使用流将Map<Integer、Integer>转换为Map<key,list<Integer>>
EN

Stack Overflow用户
提问于 2022-07-04 06:15:02
回答 3查看 83关注 0票数 0

是否有可能将一个Java Map<Integer, Integer> m0转换为一个新的Map<Integer, List<Integer>> m1,其中m1映射中的键作为m0映射的值,而值作为m0映射的键的List<Integer>

换句话说,这个任务是关于转换按值分组的键值对的。

我尝试了以下几点:

代码语言:javascript
复制
 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);
            }
        }
    }

但是第二张地图中的值是错误的。

这些价值应该是:

代码语言:javascript
复制
1 <- key Values: 1 Values: 2 Values: 3
2 <- key Values: 4 Values: 5 Values: 6 Values: 7

但我得到了:

代码语言:javascript
复制
1 <- key Values: 1 Values: 1 Values: 1
2 <- key Values: 2 Values: 2 Values: 2 Values: 2
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2022-07-04 06:43:50

它是关于按值分组的键值对的反转。

如果要像注释中所说的那样反转map,则需要在源映射的条目上创建流,而不是在值上创建流:

代码语言:javascript
复制
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));

输出:

代码语言:javascript
复制
1 -> [1, 2, 3]
2 -> [4, 5, 6, 7]
票数 2
EN

Stack Overflow用户

发布于 2022-07-04 06:42:29

代码语言:javascript
复制
 Map<Integer, List<Integer>> personByAge 
                    = m.entrySet()
                      .stream()
                      .collect(Collectors.groupingBy(
                      Map.Entry::getValue,
                     Collectors.mapping(
                     Map.Entry::getKey,
                     Collectors.toList())));
票数 0
EN

Stack Overflow用户

发布于 2022-07-04 07:08:14

下面的工作将使用forEachcomputeIfAbsent

代码语言:javascript
复制
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的示例。

代码语言:javascript
复制
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);

输出:

代码语言:javascript
复制
{1=[1, 2, 3], 2=[4, 5, 6, 7]}

因为flip返回一个SetMultimap,所以编写测试断言更容易,因为顺序在多个值上不重要。例如。可以为此示例编写以下测试。

代码语言:javascript
复制
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

代码语言:javascript
复制
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集合的提交者。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72852419

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档