java 分组依据和映射值
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/49029441/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Grouping by and map value
提问by ohwelppp
I'm trying to do grouping by (to map) and then transform list of values to different list.
我正在尝试按(映射)进行分组,然后将值列表转换为不同的列表。
I have List of DistrictDocuments:
我有地区文件列表:
List<DistrictDocument> docs = new ArrayList<>();
Then I'm streaming over it and grouping it by city:
然后我将其流式传输并按城市分组:
Map<String, List<DistrictDocument>> collect = docs.stream()
.collect(Collectors.groupingBy(DistrictDocument::getCity));
I also have a method which takes DistrictDocument and creates Slugable out of it:
我还有一个方法,它采用 DistrictDocument 并从中创建 Slugable:
private Fizz createFizz(DistrictDocument doc) {
return new Fizz().name(doc.getName()).fizz(doc.getFizz());
}
Is there a way to put that method into my stream above so I get Map<String, List<Fizz>>
?
I tried adding 2nd argument to groupingBy but couldn't find a proper way and been always getting compilation errors.
有没有办法将该方法放入我上面的流中,以便我得到Map<String, List<Fizz>>
?我尝试向 groupingBy 添加第二个参数,但找不到合适的方法并且总是出现编译错误。
Edit:
What if my createFizz returns List<Fizz>
? Is there an option to flat this list in Collectors.mapping becasue I still want to have Map<String, List<Fizz>>
instead of Map<String, List<List<Fizz>>>
编辑:如果我的 createFizz 返回List<Fizz>
怎么办?是否有一个选项可以在 Collectors.mapping 中平铺这个列表,因为我仍然想要Map<String, List<Fizz>>
而不是Map<String, List<List<Fizz>>>
回答by Eran
You need to chain a Collectors.mapping()
collector to the Collectors.groupingBy()
collector:
您需要将Collectors.mapping()
收集器链接到Collectors.groupingBy()
收集器:
Map<String, List<Fizz>> collect =
docs.stream()
.collect(Collectors.groupingBy(DistrictDocument::getCity,
Collectors.mapping(d->createFizz(d),Collectors.toList())));
If createFizz(d)
would return a List<Fizz
, you can flatten it using Java 9's Collectors.flatMapping
:
如果createFizz(d)
会返回 a List<Fizz
,您可以使用 Java 9将其展平Collectors.flatMapping
:
Map<String, List<Fizz>> collect =
docs.stream()
.collect(Collectors.groupingBy(DistrictDocument::getCity,
Collectors.flatMapping(d->createFizz(d).stream(),Collectors.toList())));
If you can't use Java 9, perhaps using Collectors.toMap
will help:
如果您不能使用 Java 9,也许使用Collectors.toMap
会有所帮助:
Map<String, List<Fizz>> collect =
docs.stream()
.collect(Collectors.toMap(DistrictDocument::getCity,
d->createFizz(d),
(l1,l2)->{l1.addAll(l2);return l1;}));
回答by Fabian
In case you'd like to do a doubly nested grouping:
如果您想进行双重嵌套分组:
Let's say you have a collection of EducationData
objects that contain School name, teacher name, and student name. But you want a nested map that looks like :
假设您有一个EducationData
包含学校名称、教师姓名和学生姓名的对象集合。但是你想要一个看起来像这样的嵌套地图:
What you have
你有什么
class EducationData {
String school;
String teacher;
String student;
// getters setters ...
}
What you want
你想要什么
Map<String, Map<String, List<String>>> desiredMapOfMpas ...
// which would look like this :
"East High School" : {
"Ms. Hymanson" : ["Derek Shepherd", "Meredith Grey", ...],
"Mr. Teresa" : ["Eleanor Shellstrop", "Jason Mendoza", ...],
....
}
How to Get There
到那里怎么走
import static java.util.stream.Collectors.*;
public doubleNestedGroup(List<EducationData> educations) {
Map<String, Map<String, List<String>>> nestedMap = educations.stream()
.collect(
groupingBy(
EducationData::getSchool,
groupingBy(
EducationData::getTeacher,
mapping(
EducationData::getStudent,
toList()
)
)
)
);
}