-1

I am trying to sort an Array of Strings based on their lengths using Comparator.comparing function. So, I have the following piece of code:

String[] arr = new String[]{"Hello","I","Am","Learning","Java"};
  1. When I try to sort it in decreasing order of their lengths, I get the results as expected using Method reference but it gives a Compile Time Error (CTE) using lambda i.e., Cannot resolve method length():
Arrays.sort(arr, Comparator.comparing(String::length).reversed()); //Using method reference
    
Arrays.sort(arr, Comparator.comparing(s->s.length()).reversed()); //Using Lambda CTE
  1. But when I sort it in increasing order of their lengths, they both yield expected results:
Arrays.sort(arr, Comparator.comparing(String::length)); //Using method reference

Arrays.sort(arr, Comparator.comparing(s->s.length())); //Using Lambda

So, why does IntelliJ throws CTE in first scenario using lambdas, when method reference can replace lambdas in scenarios involving single method invocation, so they should ideally behave the same?

Also, why the CTE described above needs to be replaced by Comparator.comparing((String s) -> s.length()).reversed()

Mehul
  • 47
  • 5
  • 2
    The problem here is not that the lambda means something different than the method reference, it is that there is not enough type information in your program to resolve the lambda. (Essentially, we've gotten spoiled by type inference; we're so used to leaving important information out of the program and having the compiler figure it out, than when we ask too much of the compiler, we think we're being reasonable.) You've combined an implicit lambda with a chained generic method inside another generic method. You're asking for the compiler to read your mind! – Brian Goetz Nov 08 '20 at 13:59
  • 2
    The solution, as the related answer says, is to provide more type information, either using an explicit lambda, an exact method reference, providing a target type for the lambda (`Comparator`), breaking the chain of method calls (pulling the comparator into its own variable), or providing an explicit type witness for the `comparing` call. – Brian Goetz Nov 08 '20 at 14:00

1 Answers1

1

You are calling generic method reversed() on a generic Comparator s->s.length(), so Comparator isn't String related at that time and therefore .length() isn't found (Object doesn't have length method)

You can define s as String:

Arrays.sort(arr, Comparator.comparing((String s)->s.length()).reversed());
Ori Marko
  • 56,308
  • 23
  • 131
  • 233