Reputation: 26077
Let's say i have 2 classes.
Course Class
public class Course {
private int id;
private String name;
}
Student Class
public class Student {
private int id;
private String name;
private List<Course> courses;
}
I have List<Student>
and each Student
is enrolled in multiple courses.
I need to filter out results using Java 8 stream API's as following.
Map<courseId, List<Student>>
I have tried below, but no success:
1st Approach
Map<Integer, List<Student>> courseStudentMap = studentList.stream()
.collect(Collectors.groupingBy(
student -> student.getCourses().stream()
.collect(Collectors.groupingBy(Course::getId))));
2nd Approach
Map<Integer, List<Student>> courseStudentMap = studentList.stream()
.filter(student -> student.getCourses().stream()
.collect(Collectors.groupingBy(
Course::getId, Collectors.mapping(Student::student, Collectors.toList()))));
Upvotes: 5
Views: 133
Reputation: 394126
Something like this should work (where SimpleEntry
is a class that implements Map.Entry<Integer,Student>
:
Map<Integer, List<Student>> courseStudentMap =
studentList.stream()
.flatMap(s -> s.getCourses()
.stream()
.map(c -> new SimpleEntry<>(c.getId(),s)))
.collect(Collectors.groupingBy(Map.Entry::getKey,
Collectors.mapping(Map.Entry::getValue,
Collectors.toList())));
The idea is to first transform the Stream<Student>
to a Stream
of all the pairs of course IDs and Student
s. Once you got that Stream
, you can use groupingBy
to obtain the desired output Map
.
Upvotes: 4
Reputation: 121048
Map<Integer, List<Student>> result = studentsList
.stream()
.flatMap(x -> x.getCourses().stream().map(y -> new SimpleEntry<>(x, y.getId())))
.collect(Collectors.groupingBy(
Entry::getValue,
Collectors.mapping(Entry::getKey, Collectors.toList())));
Upvotes: 4