I have two maps, namely
Map<String, Set<String>> courseTeacherMap = {course1: [teacher1, teacher2], ...}
Map<String, Set<String>> teacherStudentMap = {teacher1: [student1, student2], ...}
And I defined a class courseStudentPair
that has a very simple structure
public class courseStudentPair{
String studentName; // Taken from teacherStudentMap
String courseName; // Taken from courseTeacherMap
}
And my goal is to get a Set<courseStudentPair>
out of the two maps. As long as a teacher A is teaching a course C, every student that is in the value set of key A in teacherStudentMap
is considered to be a student taking C.
For example, given
Map<String, Set<String>> courseTeacherMap = {c1: [t1], c2:[t2], c3:[t1, t2]}
Map<String, Set<String>> teacherStudentMap = {t1: [s1], t2:[s1, s2]}
The result should be *(student, course) denotes a courseStudentPair object in the example below*
Set<courseStudentPair> result = [(c1, s1), (c2, s1), (c2, s2), (c3, s1), (c3, s2)]
It's quite straightforward to do it with for loops, but I am learning the stream function in Java 8 and this seems quite complicated to me. You can assume the courseStudentPair
class has constructor or builder defined.
In the same spirit, you can generate each combination of (course, teacher) and then lookup for the students associated with this teacher. This may generate duplicates (for instance (c3, s1)), so be sure your CourseStudentPair
class implements equals()
and hashCode()
based on those two fields.
import static java.util.Collections.emptySet;
import static java.util.stream.Collectors.toSet;
...
Set<CourseStudentPair> result =
courseTeacherMap.entrySet()
.stream()
.flatMap(e -> e.getValue()
.stream()
.flatMap(t -> teacherStudentMap.getOrDefault(t, emptySet()).stream().map(s -> new CourseStudentPair(e.getKey(), s))))
.collect(toSet());
/*
Output:
CourseStudentPair{studentName='c1', courseName='s1'}
CourseStudentPair{studentName='c2', courseName='s2'}
CourseStudentPair{studentName='c2', courseName='s1'}
CourseStudentPair{studentName='c3', courseName='s2'}
CourseStudentPair{studentName='c3', courseName='s1'}
*/
List<Pair<String, String>> result = courseTeacherMap.entrySet()
.stream()
.flatMap(entry -> Optional.ofNullable(entry.getValue())
.orElse(new HashSet<>())
.stream()
.flatMap(teacher -> Optional.ofNullable(teacherStudentMap.get(teacher))
.orElse(new HashSet<>())
.stream()
.map(student -> Pair.of(entry.getKey(), student))))
.distinct()
.collect(Collectors.toList());
I edited to make it null-safe, in case a teacher has no students for example or your Map
might have a key mapped to null for example.
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