我有一堂这样的课:
public class Foo {
private String a;
private String b;
private LocalDate c;
private int d;
}
我有一个列表 Foo
我想要按 a
分组的对象, b
,和c
并制作 map 。这是我到目前为止所拥有的:
Map<String, List<Foo>> test = foos.stream().collect(Collectors.groupingBy(Foo::getA, Collectors.collectingAndThen(Collectors.groupingBy(Foo::getB), Collections.unmodifiableList())));
但这本身就是错误的。我不知道如何对多个字段进行分组,但仍然产生 Map<String, List<Foo>>
。你知道我做错了什么吗?
编辑 1:如果我有以下 Foo:
{"Test", "Test", "10/02/2015", 5}
{"Test", "Test", "10/02/2015", 4}
{"Test", "Test", "10/02/2015", 3}
{"Test", "Test", "2/02/2015", 5}
{"Test", "Potato", "2/02/2015", 5}
然后它应该分组为:
{"Test", "Test", "10/02/2015", [5, 4, 3]}
{"Test", "Test", "2/02/2015", 5}
{"Test", "Potato", "2/02/2015", 5}
我原来的帖子误导了我到底想要什么,但基本上它需要按 a、b、d 分组并生成 d 列表。我知道我可能需要创建一个新类来存储它们,如下所示:
public class FooResult {
private String a;
private String b;
private LocalDate c;
private List<Integer> d;
}
如何分组并映射到如上所示的新类?
最佳答案
由于未实现多个字段的分组,因此您必须使用由 a
、b
和 c
中的值组成的复合键。有了这个键,收集操作就可以像这样与 Collector#of()
工厂方法一起使用。
Map<String, List<Integer>> result = foos.stream().collect(Collector.of(
HashMap::new,
( map, foo ) -> {
map.compute(foo.a + "_" + foo.b + "_" + foo.c, (key,list) -> {
if(list == null){
list = new ArrayList<>();
}
list.add(foo.d);
return list;
});
},
( map1, map2 ) -> {
map2.forEach(( k, v ) -> {
map1.compute(k, (key, list) -> {
if(list == null){
list = v;
} else {
list.addAll(v);
}
return list;
});
});
return map1;
}
));
关于Java 8 按多个字段分组到单个映射中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45360153/