分组和映射值

时间:2018-02-28 12:19:46

标签: java java-8 java-stream

我正在尝试按(映射)进行分组,然后将值列表转换为不同的列表。

我有DistrictDocuments列表:

List<DistrictDocument> docs = new ArrayList<>();

然后我将其流式传输并按城市分组:

Map<String, List<DistrictDocument>> collect = docs.stream()
                .collect(Collectors.groupingBy(DistrictDocument::getCity));

我还有一个方法,它接受了DistrictDocument并从中创建了Slugable:

private Fizz createFizz(DistrictDocument doc) {
    return new Fizz().name(doc.getName()).fizz(doc.getFizz());
}

有没有办法将该方法放入上面的流中,所以我得到Map<String, List<Fizz>>? 我尝试将第二个参数添加到groupingBy但是找不到合适的方法并且总是遇到编译错误。

编辑: 如果我的createFizz返回List<Fizz>怎么办?是否可以选择在Collectors.mapping中平展此列表,因为我仍然希望Map<String, List<Fizz>>代替Map<String, List<List<Fizz>>>

2 个答案:

答案 0 :(得分:15)

您需要将Collectors.mapping()收集器链接到Collectors.groupingBy()收集器:

Map<String, List<Fizz>> collect =
    docs.stream()
        .collect(Collectors.groupingBy(DistrictDocument::getCity,
                 Collectors.mapping(d->createFizz(d),Collectors.toList())));

如果createFizz(d)返回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())));

如果你不能使用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;}));

答案 1 :(得分:1)

如果您想进行双重嵌套分组:

比方说,您有EducationData个对象的集合,其中包含学校名称,老师姓名和学生姓名。但是您想要一个看起来像这样的嵌套地图:

你有什么

class EducationData {
     String school;
     String teacher;
     String student;

     // getters setters ...
}

你想要什么

Map<String, Map<String, List<String>>> desiredMapOfMpas ...

// which would look like this :

"East High School" : {
     "Ms. Jackson" : ["Derek Shepherd", "Meredith Grey", ...],
     "Mr. Teresa" : ["Eleanor Shellstrop", "Jason Mendoza", ...],
     ....
}

如何到达那里

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()
                       )
                  )
              )
        );
}