Search code examples
javajava-8java-streamcollectors

Explaining Java 8 Collector Interface/Method Signature


Stream.collect(Collector<? super T, A, R> collector)

<R,A> R collect(Collector<? super T,A,R> collector)

Performs a mutable reduction operation on the elements of this stream using a Collector.

Collectors.groupingBy​(Function<? super T,​? extends K> classifier)

public static <T,​K> Collector<T,​?,​Map<K,​List<T>>> groupingBy​(Function<? super T,​? extends K> classifier)

Returns a Collector implementing a "group by" operation on input elements of type T, grouping elements according to a classification function, and returning the results in a Map.

Can someone please explain the generics T, K and R? I'm really confused how this kind of method can conform to the signatures above:

List<Student> studentList = ....
Map<String, List<Student>> groupByTeachersMap = studentList.stream()
        .collect(Collectors.groupingBy(Student::getTeachersName));

I cannot see how collect can return Map<String, List<Student>> given the signature above. Can someone explain how to read this signature?


Solution

  • Assuming the following minimal class:

    class Student {
        String teachersName;
    
        public String getTeachersName() {
            return teachersName;
        }
    }
    

    You can relate to your code by matching the return types in and out at each step. Example, the signature for groupingBy stands as:

    // <T, K> Collector<T, ?, Map<K, List<T>>> groupingBy(Function<? super T, ? extends K> classifier)       
    

    and your specific implementation is detailed as:

    Collectors.groupingBy(new Function<Student, String>() {
        @Override
        public String apply(Student student) {
            return student.getTeachersName();
        }
    })
    

    which in your case returns

    Collector<Student, ?, Map<String, List<Student>>>
    

    and further, if you look at the signature of the collect operation i.e.

    // <R, A> R collect(Collector<? super T, A, R> collector)
    

    thereby in your case returning R as in :

    Map<String, List<Student>>