Search code examples
javacollectionsjava-8group-bycollectors

Java 8 Group by and append to a set


I have function which returns a Map<String, Set<String>>, Code before java 8:

Map<String, Set<String>> degreeMap = new HashMap<>();
for(Course  course : courses){
    Set<String> cList = degreeMap.get(course.getCourseLevel().toString());
    if(Objects.nonNull(cList)){
        cList.addAll(course.getMasterDegree()); //this is what i want to append to the old set
        degreeMap.put(course.getCourseLevel().toString(), cList);
    } else{
        degreeMap.put(course.getCourseLevel().toString(), new HashSet<>(course.getMasterDegree()));
    }
} 
return degreeMap;

Which return a map of courselevel -> set of degrees.

For example, it read all the courses and return a map like:

{"undergraduate" : ["BTech", "BSc", "BE"],
"masters": ["MTech", "MBA"],
"Executive": ["PGDBM", "EECP"]}

Here is my Course class:

public class Course {
    private List<String> masterDegree;
    private CourseLevel courseLevel;
}

But I want to write this piece of code in Java 8 style. For that, I tried this:

Map<String, Set<String>> degreeMap = courses.stream().collect(
        Collectors.groupingBy(c -> c.getCourseLevel().toString(),
                Collectors.mapping(c -> c.getMasterDegree(), Collectors.toSet()))
);

which is not working and I am getting the following compile-time error on this:

no instance(s) of type variable(s) exist so that List conforms to String inference variable T has incompatible bounds: equality constraints: String lower bounds: List

Any suggestion, how to achieve this?


Solution

  • Not tested, but looks like, you're looking for something like:

        return courses.stream()
                .collect(Collectors.toMap(course -> course.getCourseLevel().toString(),
                        course -> new HashSet<>(course.getMasterDegree()),
                        (set1, set2) -> Stream.of(set1, set2)
                                .flatMap(Set::stream).collect(Collectors.toSet())));