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:
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.
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>>>
You need to chain a Collectors.mapping()
collector to the Collectors.groupingBy()
collector:
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
:
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:
Map<String, List<Fizz>> collect = docs.stream() .collect(Collectors.toMap(DistrictDocument::getCity, d->createFizz(d), (l1,l2)->{l1.addAll(l2);return l1;}));
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 :
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() ) ) ) ); }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With