使用流将对象列表转换为Map<Long, List<>>

10

我想使用streams将一个Student对象列表转换为Map<Long, List<>>

List<Student> list = new ArrayList<Student>();
list.add(new Student("1", "test 1"));
list.add(new Student("3", "test 1"));
list.add(new Student("3", "test 3"));

我希望以下是最终结果:

地图

键: 1

值列表: Student("1", "测试1")

键: 3

值列表: Student("3", "测试1"), Student("3", "测试3")

我尝试了以下代码,但它正在重新初始化Student对象。有人可以帮我修复下面的代码吗?

Map<Long, List<Student>> map = list.stream()
                        .collect(Collectors.groupingBy(
                                Student::getId,
                                Collectors.mapping(Student::new, Collectors.toList())
                        ));
5个回答

14

您不需要链接mapping收集器。单个参数groupingBy会默认给您一个Map<Long, List<Student>>

Map<Long, List<Student>> map = 
    list.stream()
        .collect(Collectors.groupingBy(Student::getId));

1
这些 id 看起来像是字符串啊 :P - daniu

6
Eran的回答 是正确的。补充一点,你也可以使用一个Supplier
Map<Long, List<Student>> map = 
    list.stream()
        .collect(Collectors.groupingBy(Student::getId, TreeMap::new, Collectors.toList()));

4
对于这类简单的用例,我更喜欢查看Eclipse Collections而不是依赖于创建Stream所需的开销。
结果相同,它会给你一个java.util.Map,而且我觉得语法更加简洁。
MutableList<Student> list = Lists.mutable.of();
list.add(new Student("1", "test 1"));
list.add(new Student("3", "test 1"));
list.add(new Student("3", "test 3"));

Map<String, List<Student>> map = list.groupBy(Student::getId).toMap(ArrayList::new);

1
这确实看起来非常清晰易懂。我曾听说过这个API,但是通过你的回答第一次看到它的实际应用。 - Arvind Kumar Avinash
1
@ArvindKumarAvinash 谢谢,我想我会继续回答更多问题,并且加入这个库的示例,它非常好。 - Yassin Hajaj
在编写了这个答案之后,我想确认一下是否可以使用Eclipse Collections API进一步简化它。如果可以,请为了未来访问者的利益发布相应的内容。 - Arvind Kumar Avinash
1
嗨@ArvindKumarAvinash,谢谢你想到我,我会立刻检查 :) - Yassin Hajaj

0

使用toMap作为groupingBy的替代方案:

Map<Long, List<Student>> result = list.stream()
                                      .collect(Collectors.toMap(Student::getId,
                                                                s-> { List<Student> l = new ArrayList<>();
                                                                      l.add(s);
                                                                      return l;
                                                                    },
                                                                    (l1,l2)-> { l1.addAll(l2); 
                                                                                return l1;}));

0

@Eran提供的答案很直接,但如果您想在此上下文中更改数据类型StringLong,那么您可以使用lambda表达式String转换为Long

Map<Long, List<Student>> map = 
    list.stream()
        .collect(Collectors.groupingBy(s ->Long.parseLong(s.getId())));

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接