Home > OS >  Get a Map<String, List<String>> from List<Pojo>
Get a Map<String, List<String>> from List<Pojo>

Time:04-21

I have a Student class with the following structure:

class Student {
    String name;
    int age;
    String grade;        
}    

I have a List of Students (let's call it students) like this:

[{"Student1", 10, "A1"}, {"Student2", 12, "A2"}, {"Student1", 11, "A1"}, {"Student4", 11, "A1"}, {"Student5", 10, "A2"}, {"Student6", 10, "A1"}, {"Student2", 13, "A2"}, {"Student7", 11, "B1"}]

Using the following code:

Map<String,List<Student>> groupedMap =
students.stream().collect(Collectors.groupingBy(Student::getGrade));

I am able to get a Map<String, List<Student>> like this:

{
"A1" : [{"Student1", 10, "A1"}, {"Student1", 11, "A1"}, {"Student4", 11, "A1"}, {"Student6", 10, "A1"}],
"A2" : [{"Student2", 12, "A2"}, {"Student5", 10, "A2"}, {"Student2", 13, "A2"}],
"B1" : [{"Student7", 11, "B1"}]
}

However, I want a Map<String, List<String>> instead of the above Map<String,List<Student>>.

The "key" of this Map would be the same, that is, the "grade" property of the Student class.

The "value" of this map should be the List of the names of all Students having that particular grade. Duplicates should also be removed from this "value" List, since there can be multiple students with the same name. Also, if possible, I need the insertion order preserved in this list.

For example, the output in this case would be:

{
"A1" : ["Student1", "Student4", "Student6"],
"A2" : ["Student2", "Student5"],
"B1" : ["Student7"]
}

CodePudding user response:

The following code will give the result. Though duplicates would be removed and insertion order preserved in the "value" of the Map, it would however still be a Set.

Map<String, Set<String>> groupedMap =
students.stream()
  .collect(Collectors.groupingBy(Student::getGrade,
        Collectors.mapping(Student::getName, Collectors.toCollection(LinkedHashSet::new))));

If, however, we need the "value" as a List only (of course with duplicates removed) instead of a Set, then we can use the following code:

Map<String, List<String>> groupedMap =
students.stream()
  .collect(Collectors.groupingBy(Student::getGrade,
        Collectors.mapping(Student::getName,
              Collectors.collectingAndThen(
                    Collectors.toCollection(
                          LinkedHashSet::new), ArrayList::new))));

CodePudding user response:

Use downstream collector to map the Student to name.

 students.stream()
                .collect(Collectors.groupingBy(Student::getGrade, 
                         Collectors.mapping(Student::getName, Collectors.toList())));
  • Related