I have a Student
class with the following structure:
class Student {
String name;
int age;
String grade;
}
I have a List
of Student
s (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())));