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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 10:14:48  来源:igfitidea点击:

Grouping by and map value

javajava-8java-stream

提问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.toMapwill 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 EducationDataobjects 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()
                       )
                  )
              )
        );
}