Search code examples
javalambdajava-8java-stream

Method referencing is not working in collect method for stream


I'm trying to sort the elements in the list and collect and print it in separate list using java 8 streams below is the code.

Working Code:

System.out.println(coursesList.stream()
        .sorted(comparingByNoOfStudents).collect(Collectors.toList()));

But when it try the same with method referencing it's giving error:

 System.out.println(coursesList.stream()
        .sorted(comparingByNoOfStudents).collect(Collectors::toList));

Below is the message :

java: no suitable method found for collect(Collectors::toList)
    method java.util.stream.Stream.<R>collect(java.util.function.Supplier<R>,java.util.function.BiConsumer<R,? super com.java.functional.basic.Courses>,java.util.function.BiConsumer<R,R>) is not applicable
      (cannot infer type-variable(s) R
        (actual and formal argument lists differ in length))
    method java.util.stream.Stream.<R,A>collect(java.util.stream.Collector<? super com.java.functional.basic.Courses,A,R>) is not applicable
      (cannot infer type-variable(s) R,A
        (argument mismatch; java.util.stream.Collector is not a functional interface
          multiple non-overriding abstract methods found in interface java.util.stream.Collector))

Solution

  • Yes, of course. You need to pass a collector to collect. Not 'a method that can make a collector', you pass a collector.

    a method reference is way to say: Don't call the method - instead, I want the concept of the method call as a thing I can hand off so that other folks can actually call it.

    Take the .sorted method which can sort it for you if you provide a function that tells you which of any 2 elements is 'the earlier' one. You do not want to run this 'which one is earlier, a or b?' method, you want to hand it off.

    That's what lambdas (-> syntax) and method references (which is just shorthand for x -> invokeThatMethod(x)) are for. the collect method doesn't ever want one.