How to use Java 8 Collectors groupingBy to get a Map with a Map of the collection?

alexzm1 picture alexzm1 · Jun 14, 2015 · Viewed 13.2k times · Source

Imagine these classes

class Subject {
   private int id;
   private Type type;
   private String origin;
   private String name;

   Subject(int id, Type type, String origin, String name) {
      this.id = id;
      this.type = type;
      this.origin = origin;
      this.name = name;
   }

   // Getters and Setters
}

enum Type {
   TYPE1,
   TYPE2
}

I have a list of those Subject classes

List<Subject> subjects = Arrays.asList(
    new Subject(1, Type.TYPE1, "South", "Oscar"),
    new Subject(2, Type.TYPE2, "South", "Robert"),
    new Subject(3, Type.TYPE2, "North", "Dan"),
    new Subject(4, Type.TYPE2, "South", "Gary"));

I would like to get as a result of using Collectors.groupingBy() a Map grouping first the Subject objects by Subject.origin and then grouped by Subject.type

Getting as a result an object like this Map<String, Map<Type, List<Subject>>>

Answer

Misha picture Misha · Jun 14, 2015

groupingBy accepts a downstream collector, which can also be a groupingBy:

subjects.stream()
        .collect(groupingBy(
                Subject::getOrigin, 
                groupingBy(Subject::getType)    
        ));