I want to convert a nested map structure created by java streams + groupingBy into a list of POJOs, where each POJO represents one of the groups and also holds all the matching objects of that group.
I have the following code: I use project lombok for convenience here (@Builder, @Data). Please let me know if that is confusing.
My goal is to prevent two points from happening:
- Having deeply nested maps and
- As a result: Looping over these nested maps via keySets or entrySets to actually do stuff if the entries
Instead, I'd love a clean and flat list of POJOs that represent the grouping and conveniently hold the matching entries for each group.
Find the code on GitHub to run if locally, if you want.
Edit 1: I've updated the code again to remove the lastname and add another "Gerrit" object to have two objects with the same grouping. I hope this makes the intent clearer.
Edit 2: I have updated the code again to add a property on Person which is not part of the grouping.
I am looking for an output like this:
[
Grouping(firstname=Jane, age=24, homeCountry=USA, persons=[Person(firstname=Jane, age=24, homeCountry=USA, favoriteColor=yellow)]),
Grouping(firstname=gerrit, age=24, homeCountry=germany, persons=[
Person(firstname=gerrit, age=24, homeCountry=germany, favoriteColor=blue), Person(firstname=gerrit, age=24, homeCountry=germany, favoriteColor=green)
])
]
public class ConvertMapStreamToPojo {
@Data
@Builder
static class Person {
private String firstname;
private int age;
private String homeCountry;
private String favoriteColor;
}
@Data
static class Grouping {
private String firstname;
private int age;
private String homeCountry;
List<Person> persons;
}
public static void main(String[] args) {
Person gerrit = Person.builder()
.firstname("gerrit")
.age(24)
.homeCountry("germany")
.favoriteColor("blue")
.build();
Person anotherGerrit = Person.builder()
.firstname("gerrit")
.age(24)
.homeCountry("germany")
.favoriteColor("green")
.build();
Person janeDoe = Person.builder()
.firstname("Jane")
.age(25)
.homeCountry("USA")
.favoriteColor("yellow")
.build();
List<Person> persons = Arrays.asList(gerrit, anotherGerrit, janeDoe);
Map<String, Map<Integer, Map<String, List<Person>>>> nestedGroupings = persons.stream()
.collect(
Collectors.groupingBy(Person::getFirstname,
Collectors.groupingBy(Person::getAge,
Collectors.groupingBy(Person::getHomeCountry)
)
)
);
/**
* Convert the nested maps into a List<Groupings> where each group
* holds a list of all matching persons
*/
List<Grouping> groupings = new ArrayList<>();
for (Grouping grouping: groupings) {
String message = String.format("Grouping for firstname %s age %s and country %s", grouping.getFirstname(), grouping.getAge(), grouping.getHomeCountry());
System.out.println(message);
System.out.println("Number of persons inside this grouping: " + grouping.getPersons().size());
}
// example groupings
/**
*
* [
* Grouping(firstname=Jane, age=24, homeCountry=USA, persons=[Person(firstname=Jane, age=24, homeCountry=USA, favoriteColor=yellow)]),
* Grouping(firstname=gerrit, age=24, homeCountry=germany, persons=[
* Person(firstname=gerrit, age=24, homeCountry=germany, favoriteColor=blue), Person(firstname=gerrit, age=24, homeCountry=germany, favoriteColor=green)
* ])
* ]
*
*/
}
}