Java 8 stream max() function argument type Comparator vs ComparableJava 8 stream's .min() and .max(): why does this compile?How do I compare strings in Java?Comparing Java enum members: == or equals()?Best practice for compareTo() when argument must be typed of super classIs there a concise way to iterate over a stream with indices in Java 8?Custom thread pool in Java 8 parallel streamHow to Convert a Java 8 Stream to an Array?Convert Iterable to Stream using Java 8 JDKWhy are Java Streams once-off?How to sum a list of integers with java streams?Java Generics Clarification( Constraining T to a type, while using Comparable)

What do you do if you have developments on your paper during the long peer review process?

Painting a 4x6 grid with 2 colours

How is the problem, ⟨G⟩ in Logspace?

Do things made of adamantine rust?

What is the meaning of "heutig" in this sentence?

Where Does VDD+0.3V Input Limit Come From on IC chips?

On the meaning of 'anyways' in "What Exactly Is a Quartz Crystal, Anyways?"

Where are they calling from?

Why does this image of Jupiter look so strange?

Writing a letter of recommendation for a mediocre student

What is the need of methods like GET and POST in the HTTP protocol?

What exactly did this mechanic sabotage on the American Airlines 737, and how dangerous was it?

Which place in our solar system is mostly fit for terraforming?

Strange Sticky Substance on Digital Camera

I reverse the source code, you negate the output!

Two trains move towards each other, a bird moves between them. How many trips can the bird make?

Is it impolite to ask for an in-flight catalogue with no intention of buying?

Should the average user with no special access rights be worried about SMS-based 2FA being theoretically interceptable?

How do you use the interjection for snorting?

What is this utensil for?

Can a broken/split chain be reassembled?

Safely hang a mirror that does not have hooks

Hiking with a mule or two?

Late 1970's and 6502 chip facilities for operating systems



Java 8 stream max() function argument type Comparator vs Comparable


Java 8 stream's .min() and .max(): why does this compile?How do I compare strings in Java?Comparing Java enum members: == or equals()?Best practice for compareTo() when argument must be typed of super classIs there a concise way to iterate over a stream with indices in Java 8?Custom thread pool in Java 8 parallel streamHow to Convert a Java 8 Stream to an Array?Convert Iterable to Stream using Java 8 JDKWhy are Java Streams once-off?How to sum a list of integers with java streams?Java Generics Clarification( Constraining T to a type, while using Comparable)






.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty margin-bottom:0;








17















I wrote some simple code like below. This class works fine without any errors.



public class Test 
public static void main(String[] args)
List<Integer> intList = IntStream.of(1,2,3,4,5,6,7,8,9,10).boxed().collect(Collectors.toList());
int value = intList.stream().max(Integer::compareTo).get();

//int value = intList.stream().max(<Comparator<? super T> comparator type should pass here>).get();

System.out.println("value :"+value);




As the code comment shows the max() method should pass an argument of type Comparator<? super Integer>.



But Integer::compareTo implements Comparable interface - not Comparator.



public final class Integer extends Number implements Comparable<Integer> 
public int compareTo(Integer anotherInteger)
return compare(this.value, anotherInteger.value);




How can this work? The max() method says it needs a Comparator argument, but it works with Comparable argument.



I know I have misunderstood something, but I do now know what. Can someone please explain?










share|improve this question





















  • 4





    Integer::compareTo does not return a Comparable - it is the short definition for: "Please compiler generate a matching implementation for the type that is needed (in this case Comparator) and map the arguments to the specified function." In this case the function requires two "arguments" (this and the one parameter of compareTo) and the Comparator provides two arguments -> works.

    – Robert
    Apr 15 at 18:37







  • 6





    ""Please compiler, generate..." ... compilers always respond best to politeness and courtesy :-)

    – scottb
    Apr 15 at 18:45






  • 1





    Related: stackoverflow.com/questions/22561614/…

    – Oleksandr Pyrohov
    Apr 15 at 22:27

















17















I wrote some simple code like below. This class works fine without any errors.



public class Test 
public static void main(String[] args)
List<Integer> intList = IntStream.of(1,2,3,4,5,6,7,8,9,10).boxed().collect(Collectors.toList());
int value = intList.stream().max(Integer::compareTo).get();

//int value = intList.stream().max(<Comparator<? super T> comparator type should pass here>).get();

System.out.println("value :"+value);




As the code comment shows the max() method should pass an argument of type Comparator<? super Integer>.



But Integer::compareTo implements Comparable interface - not Comparator.



public final class Integer extends Number implements Comparable<Integer> 
public int compareTo(Integer anotherInteger)
return compare(this.value, anotherInteger.value);




How can this work? The max() method says it needs a Comparator argument, but it works with Comparable argument.



I know I have misunderstood something, but I do now know what. Can someone please explain?










share|improve this question





















  • 4





    Integer::compareTo does not return a Comparable - it is the short definition for: "Please compiler generate a matching implementation for the type that is needed (in this case Comparator) and map the arguments to the specified function." In this case the function requires two "arguments" (this and the one parameter of compareTo) and the Comparator provides two arguments -> works.

    – Robert
    Apr 15 at 18:37







  • 6





    ""Please compiler, generate..." ... compilers always respond best to politeness and courtesy :-)

    – scottb
    Apr 15 at 18:45






  • 1





    Related: stackoverflow.com/questions/22561614/…

    – Oleksandr Pyrohov
    Apr 15 at 22:27













17












17








17


3






I wrote some simple code like below. This class works fine without any errors.



public class Test 
public static void main(String[] args)
List<Integer> intList = IntStream.of(1,2,3,4,5,6,7,8,9,10).boxed().collect(Collectors.toList());
int value = intList.stream().max(Integer::compareTo).get();

//int value = intList.stream().max(<Comparator<? super T> comparator type should pass here>).get();

System.out.println("value :"+value);




As the code comment shows the max() method should pass an argument of type Comparator<? super Integer>.



But Integer::compareTo implements Comparable interface - not Comparator.



public final class Integer extends Number implements Comparable<Integer> 
public int compareTo(Integer anotherInteger)
return compare(this.value, anotherInteger.value);




How can this work? The max() method says it needs a Comparator argument, but it works with Comparable argument.



I know I have misunderstood something, but I do now know what. Can someone please explain?










share|improve this question
















I wrote some simple code like below. This class works fine without any errors.



public class Test 
public static void main(String[] args)
List<Integer> intList = IntStream.of(1,2,3,4,5,6,7,8,9,10).boxed().collect(Collectors.toList());
int value = intList.stream().max(Integer::compareTo).get();

//int value = intList.stream().max(<Comparator<? super T> comparator type should pass here>).get();

System.out.println("value :"+value);




As the code comment shows the max() method should pass an argument of type Comparator<? super Integer>.



But Integer::compareTo implements Comparable interface - not Comparator.



public final class Integer extends Number implements Comparable<Integer> 
public int compareTo(Integer anotherInteger)
return compare(this.value, anotherInteger.value);




How can this work? The max() method says it needs a Comparator argument, but it works with Comparable argument.



I know I have misunderstood something, but I do now know what. Can someone please explain?







java java-8 java-stream






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Apr 15 at 19:37









MyStackRunnethOver

1,4791 gold badge9 silver badges19 bronze badges




1,4791 gold badge9 silver badges19 bronze badges










asked Apr 15 at 16:57









ShalikaShalika

4961 gold badge7 silver badges20 bronze badges




4961 gold badge7 silver badges20 bronze badges










  • 4





    Integer::compareTo does not return a Comparable - it is the short definition for: "Please compiler generate a matching implementation for the type that is needed (in this case Comparator) and map the arguments to the specified function." In this case the function requires two "arguments" (this and the one parameter of compareTo) and the Comparator provides two arguments -> works.

    – Robert
    Apr 15 at 18:37







  • 6





    ""Please compiler, generate..." ... compilers always respond best to politeness and courtesy :-)

    – scottb
    Apr 15 at 18:45






  • 1





    Related: stackoverflow.com/questions/22561614/…

    – Oleksandr Pyrohov
    Apr 15 at 22:27












  • 4





    Integer::compareTo does not return a Comparable - it is the short definition for: "Please compiler generate a matching implementation for the type that is needed (in this case Comparator) and map the arguments to the specified function." In this case the function requires two "arguments" (this and the one parameter of compareTo) and the Comparator provides two arguments -> works.

    – Robert
    Apr 15 at 18:37







  • 6





    ""Please compiler, generate..." ... compilers always respond best to politeness and courtesy :-)

    – scottb
    Apr 15 at 18:45






  • 1





    Related: stackoverflow.com/questions/22561614/…

    – Oleksandr Pyrohov
    Apr 15 at 22:27







4




4





Integer::compareTo does not return a Comparable - it is the short definition for: "Please compiler generate a matching implementation for the type that is needed (in this case Comparator) and map the arguments to the specified function." In this case the function requires two "arguments" (this and the one parameter of compareTo) and the Comparator provides two arguments -> works.

– Robert
Apr 15 at 18:37






Integer::compareTo does not return a Comparable - it is the short definition for: "Please compiler generate a matching implementation for the type that is needed (in this case Comparator) and map the arguments to the specified function." In this case the function requires two "arguments" (this and the one parameter of compareTo) and the Comparator provides two arguments -> works.

– Robert
Apr 15 at 18:37





6




6





""Please compiler, generate..." ... compilers always respond best to politeness and courtesy :-)

– scottb
Apr 15 at 18:45





""Please compiler, generate..." ... compilers always respond best to politeness and courtesy :-)

– scottb
Apr 15 at 18:45




1




1





Related: stackoverflow.com/questions/22561614/…

– Oleksandr Pyrohov
Apr 15 at 22:27





Related: stackoverflow.com/questions/22561614/…

– Oleksandr Pyrohov
Apr 15 at 22:27












4 Answers
4






active

oldest

votes


















20
















int value = intList.stream().max(Integer::compareTo).get();


The above snippet of code is logically equivalent to the following:



int value = intList.stream().max((a, b) -> a.compareTo(b)).get();


Which is also logically equivalent to the following:



int value = intList.stream().max(new Comparator<Integer>() 
@Override
public int compare(Integer a, Integer b)
return a.compareTo(b);

).get();


Comparator is a functional interface and can be used as a lambda or method reference, which is why your code compiles and executes successfully.



I recommend reading Oracle's tutorial on Method References (they use an example where two objects are compared) as well as the Java Language Specification on §15.13. Method Reference Expressions to understand why this works.






share|improve this answer






















  • 9





    Although it's absolutely correct, it doesn't answer "How can this work?"

    – Andrew Tobilko
    Apr 15 at 17:18


















13
















I can relate to your confusion.



We've got a Comparator's method which declares two parameters



int compare(T o1, T o2);


and we've got an Integer's method which takes one parameter



int compareTo(Integer anotherInteger)


How on earth does Integer::compareTo get resolved to a Comparator instance?



When a method reference points to an instance method, the parser can look for methods with arity n-1 (n is the expected number of parameters).



Here's an excerpt from the JLS on how applicable methods are identified. I will drop the first part about parsing the expression preceding the :: token.




Second, given a targeted function type with n parameters, a set of potentially applicable methods is identified:



If the method reference expression has the form ReferenceType :: [TypeArguments] Identifier, then the potentially applicable methods are:



  • the member methods of the type to search that would be potentially applicable (§15.12.2.1) for a method invocation which names Identifier, has arity n, has type arguments TypeArguments, and appears in the same class as the method reference expression; plus


  • the member methods of the type to search that would be potentially applicable for a method invocation which names Identifier, has arity n-1, has type arguments TypeArguments, and appears in the same class as the method reference expression.


Two different arities, n and n-1, are considered, to account for the possibility that this form refers to either a static method or an instance method.



...



A method reference expression of the form ReferenceType :: [TypeArguments] Identifier can be interpreted in different ways. If Identifier refers to an instance method, then the implicit lambda expression has an extra parameter compared to if Identifier refers to a static method.



https://docs.oracle.com/javase/specs/jls/se12/html/jls-15.html#jls-15.13.1




If we were to write an implicit lambda expression from that method reference, the first (implicit) parameter would be an instance to call the method on, the second (explicit) parameter would be an argument to pass in the method.



(implicitParam, anotherInteger) -> implicitParam.compareTo(anotherInteger)


Note that a method reference differs from a lambda expression, even though the former can be easily transformed into the latter. A lambda expression needs to be desugared into a new method, while a method reference usually requires only loading a corresponding constant method handle.




Integer::compareTo implements Comparable interface - not Comparator.




Integer::compareTo as an expression doesn't implement any interface. However, it can refer to/represent different functional types, one of which is Comparator<Integer>.



Comparator<Integer> a = Integer::compareTo;
BiFunction<Integer, Integer, Integer> b = Integer::compareTo;
ToIntBiFunction<Integer, Integer> c = Integer::compareTo;





share|improve this answer


































    7
















    Integer implements Comparable by overriding compareTo.



    That overriden compareTo, however, can be used in a way that satisfies and implements the Comparator interface.



    In its usage here



    int value = intList.stream().max(Integer::compareTo).get();


    it's translated to something like



    int value = intList.stream().max(new Comparator<Integer>() 
    @Override
    public int compare(Integer o1, Integer o2)
    return o1.compareTo(o2);

    ).get();


    A method reference (or lambda expression) must satisfy the signature of the corresponding functional interface's single abstract method and, in this case (Comparator), compareTo does.




    The idea is that max expects a Comparator and its compare method expects two Integer objects. Integer::compareTo can satisfy those expectations because it also expects two Integer objects. The first is its receiver (the instance on which the method is to be called) and the second is the argument. With the new Java 8 syntax, the compiler translates one style to the other.



    (compareTo also returns an int as required by Comparator#compare.)






    share|improve this answer






















    • 1





      how does Integer::compareTo satisfy the signature of Comparator#compare? compareTo(Integer) vs compare(Integer, Integer)?

      – Andrew Tobilko
      Apr 15 at 21:30







    • 1





      I disagree with "the compiler translates one style to the other". I think the compiler may validate a syntactic construct, but not translate it into another one. I am sure the compiler doesn't turn a method reference in a lambda. I didn't downvote your answer, btw.

      – Andrew Tobilko
      Apr 16 at 7:02


















    1
















    First trick: all instance methods actually take 1 additional implicit argument, the one you refer to as this in method body. E.g.:



    public final class Integer extends Number implements Comparable<Integer> 
    public int compareTo(/* Integer this, */ Integer anotherInteger)
    return compare(this.value, anotherInteger.value);



    Integer a = 10, b = 100;
    int compareResult = a.compareTo(b);
    // this actually 'compiles' to Integer#compareTo(this = a, anotherInteger = b)


    Second trick: Java compiler can "transform" the signature of a method reference to some functional interface, if the number and types of arguments (including this) satisfy:



    interface MyInterface 
    int foo(Integer bar, Integer baz);


    Integer a = 100, b = 1000;

    int result1 = ((Comparator<Integer>) Integer::compareTo).compare(a, b);
    int result2 = ((BiFunction<Integer, Integer, Integer>) Integer::compareTo).apply(a, b);
    int result3 = ((MyInterface) Integer::compareTo).foo(a, b);

    // result1 == result2 == result3


    As you can see class Integer implements none of Comparator, BiFunction or a random MyInterface, but that doesn't stop you from casting the Integer::compareTo method reference as those interfaces.






    share|improve this answer





























      Your Answer






      StackExchange.ifUsing("editor", function ()
      StackExchange.using("externalEditor", function ()
      StackExchange.using("snippets", function ()
      StackExchange.snippets.init();
      );
      );
      , "code-snippets");

      StackExchange.ready(function()
      var channelOptions =
      tags: "".split(" "),
      id: "1"
      ;
      initTagRenderer("".split(" "), "".split(" "), channelOptions);

      StackExchange.using("externalEditor", function()
      // Have to fire editor after snippets, if snippets enabled
      if (StackExchange.settings.snippets.snippetsEnabled)
      StackExchange.using("snippets", function()
      createEditor();
      );

      else
      createEditor();

      );

      function createEditor()
      StackExchange.prepareEditor(
      heartbeatType: 'answer',
      autoActivateHeartbeat: false,
      convertImagesToLinks: true,
      noModals: true,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: 10,
      bindNavPrevention: true,
      postfix: "",
      imageUploader:
      brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
      contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/4.0/"u003ecc by-sa 4.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
      allowUrls: true
      ,
      onDemand: true,
      discardSelector: ".discard-answer"
      ,immediatelyShowMarkdownHelp:true
      );



      );














      draft saved

      draft discarded
















      StackExchange.ready(
      function ()
      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55694015%2fjava-8-stream-max-function-argument-type-comparator-vs-comparable%23new-answer', 'question_page');

      );

      Post as a guest















      Required, but never shown

























      4 Answers
      4






      active

      oldest

      votes








      4 Answers
      4






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes









      20
















      int value = intList.stream().max(Integer::compareTo).get();


      The above snippet of code is logically equivalent to the following:



      int value = intList.stream().max((a, b) -> a.compareTo(b)).get();


      Which is also logically equivalent to the following:



      int value = intList.stream().max(new Comparator<Integer>() 
      @Override
      public int compare(Integer a, Integer b)
      return a.compareTo(b);

      ).get();


      Comparator is a functional interface and can be used as a lambda or method reference, which is why your code compiles and executes successfully.



      I recommend reading Oracle's tutorial on Method References (they use an example where two objects are compared) as well as the Java Language Specification on §15.13. Method Reference Expressions to understand why this works.






      share|improve this answer






















      • 9





        Although it's absolutely correct, it doesn't answer "How can this work?"

        – Andrew Tobilko
        Apr 15 at 17:18















      20
















      int value = intList.stream().max(Integer::compareTo).get();


      The above snippet of code is logically equivalent to the following:



      int value = intList.stream().max((a, b) -> a.compareTo(b)).get();


      Which is also logically equivalent to the following:



      int value = intList.stream().max(new Comparator<Integer>() 
      @Override
      public int compare(Integer a, Integer b)
      return a.compareTo(b);

      ).get();


      Comparator is a functional interface and can be used as a lambda or method reference, which is why your code compiles and executes successfully.



      I recommend reading Oracle's tutorial on Method References (they use an example where two objects are compared) as well as the Java Language Specification on §15.13. Method Reference Expressions to understand why this works.






      share|improve this answer






















      • 9





        Although it's absolutely correct, it doesn't answer "How can this work?"

        – Andrew Tobilko
        Apr 15 at 17:18













      20














      20










      20









      int value = intList.stream().max(Integer::compareTo).get();


      The above snippet of code is logically equivalent to the following:



      int value = intList.stream().max((a, b) -> a.compareTo(b)).get();


      Which is also logically equivalent to the following:



      int value = intList.stream().max(new Comparator<Integer>() 
      @Override
      public int compare(Integer a, Integer b)
      return a.compareTo(b);

      ).get();


      Comparator is a functional interface and can be used as a lambda or method reference, which is why your code compiles and executes successfully.



      I recommend reading Oracle's tutorial on Method References (they use an example where two objects are compared) as well as the Java Language Specification on §15.13. Method Reference Expressions to understand why this works.






      share|improve this answer















      int value = intList.stream().max(Integer::compareTo).get();


      The above snippet of code is logically equivalent to the following:



      int value = intList.stream().max((a, b) -> a.compareTo(b)).get();


      Which is also logically equivalent to the following:



      int value = intList.stream().max(new Comparator<Integer>() 
      @Override
      public int compare(Integer a, Integer b)
      return a.compareTo(b);

      ).get();


      Comparator is a functional interface and can be used as a lambda or method reference, which is why your code compiles and executes successfully.



      I recommend reading Oracle's tutorial on Method References (they use an example where two objects are compared) as well as the Java Language Specification on §15.13. Method Reference Expressions to understand why this works.







      share|improve this answer














      share|improve this answer



      share|improve this answer








      edited Apr 15 at 17:33

























      answered Apr 15 at 17:02









      Jacob G.Jacob G.

      19k5 gold badges26 silver badges71 bronze badges




      19k5 gold badges26 silver badges71 bronze badges










      • 9





        Although it's absolutely correct, it doesn't answer "How can this work?"

        – Andrew Tobilko
        Apr 15 at 17:18












      • 9





        Although it's absolutely correct, it doesn't answer "How can this work?"

        – Andrew Tobilko
        Apr 15 at 17:18







      9




      9





      Although it's absolutely correct, it doesn't answer "How can this work?"

      – Andrew Tobilko
      Apr 15 at 17:18





      Although it's absolutely correct, it doesn't answer "How can this work?"

      – Andrew Tobilko
      Apr 15 at 17:18













      13
















      I can relate to your confusion.



      We've got a Comparator's method which declares two parameters



      int compare(T o1, T o2);


      and we've got an Integer's method which takes one parameter



      int compareTo(Integer anotherInteger)


      How on earth does Integer::compareTo get resolved to a Comparator instance?



      When a method reference points to an instance method, the parser can look for methods with arity n-1 (n is the expected number of parameters).



      Here's an excerpt from the JLS on how applicable methods are identified. I will drop the first part about parsing the expression preceding the :: token.




      Second, given a targeted function type with n parameters, a set of potentially applicable methods is identified:



      If the method reference expression has the form ReferenceType :: [TypeArguments] Identifier, then the potentially applicable methods are:



      • the member methods of the type to search that would be potentially applicable (§15.12.2.1) for a method invocation which names Identifier, has arity n, has type arguments TypeArguments, and appears in the same class as the method reference expression; plus


      • the member methods of the type to search that would be potentially applicable for a method invocation which names Identifier, has arity n-1, has type arguments TypeArguments, and appears in the same class as the method reference expression.


      Two different arities, n and n-1, are considered, to account for the possibility that this form refers to either a static method or an instance method.



      ...



      A method reference expression of the form ReferenceType :: [TypeArguments] Identifier can be interpreted in different ways. If Identifier refers to an instance method, then the implicit lambda expression has an extra parameter compared to if Identifier refers to a static method.



      https://docs.oracle.com/javase/specs/jls/se12/html/jls-15.html#jls-15.13.1




      If we were to write an implicit lambda expression from that method reference, the first (implicit) parameter would be an instance to call the method on, the second (explicit) parameter would be an argument to pass in the method.



      (implicitParam, anotherInteger) -> implicitParam.compareTo(anotherInteger)


      Note that a method reference differs from a lambda expression, even though the former can be easily transformed into the latter. A lambda expression needs to be desugared into a new method, while a method reference usually requires only loading a corresponding constant method handle.




      Integer::compareTo implements Comparable interface - not Comparator.




      Integer::compareTo as an expression doesn't implement any interface. However, it can refer to/represent different functional types, one of which is Comparator<Integer>.



      Comparator<Integer> a = Integer::compareTo;
      BiFunction<Integer, Integer, Integer> b = Integer::compareTo;
      ToIntBiFunction<Integer, Integer> c = Integer::compareTo;





      share|improve this answer































        13
















        I can relate to your confusion.



        We've got a Comparator's method which declares two parameters



        int compare(T o1, T o2);


        and we've got an Integer's method which takes one parameter



        int compareTo(Integer anotherInteger)


        How on earth does Integer::compareTo get resolved to a Comparator instance?



        When a method reference points to an instance method, the parser can look for methods with arity n-1 (n is the expected number of parameters).



        Here's an excerpt from the JLS on how applicable methods are identified. I will drop the first part about parsing the expression preceding the :: token.




        Second, given a targeted function type with n parameters, a set of potentially applicable methods is identified:



        If the method reference expression has the form ReferenceType :: [TypeArguments] Identifier, then the potentially applicable methods are:



        • the member methods of the type to search that would be potentially applicable (§15.12.2.1) for a method invocation which names Identifier, has arity n, has type arguments TypeArguments, and appears in the same class as the method reference expression; plus


        • the member methods of the type to search that would be potentially applicable for a method invocation which names Identifier, has arity n-1, has type arguments TypeArguments, and appears in the same class as the method reference expression.


        Two different arities, n and n-1, are considered, to account for the possibility that this form refers to either a static method or an instance method.



        ...



        A method reference expression of the form ReferenceType :: [TypeArguments] Identifier can be interpreted in different ways. If Identifier refers to an instance method, then the implicit lambda expression has an extra parameter compared to if Identifier refers to a static method.



        https://docs.oracle.com/javase/specs/jls/se12/html/jls-15.html#jls-15.13.1




        If we were to write an implicit lambda expression from that method reference, the first (implicit) parameter would be an instance to call the method on, the second (explicit) parameter would be an argument to pass in the method.



        (implicitParam, anotherInteger) -> implicitParam.compareTo(anotherInteger)


        Note that a method reference differs from a lambda expression, even though the former can be easily transformed into the latter. A lambda expression needs to be desugared into a new method, while a method reference usually requires only loading a corresponding constant method handle.




        Integer::compareTo implements Comparable interface - not Comparator.




        Integer::compareTo as an expression doesn't implement any interface. However, it can refer to/represent different functional types, one of which is Comparator<Integer>.



        Comparator<Integer> a = Integer::compareTo;
        BiFunction<Integer, Integer, Integer> b = Integer::compareTo;
        ToIntBiFunction<Integer, Integer> c = Integer::compareTo;





        share|improve this answer





























          13














          13










          13









          I can relate to your confusion.



          We've got a Comparator's method which declares two parameters



          int compare(T o1, T o2);


          and we've got an Integer's method which takes one parameter



          int compareTo(Integer anotherInteger)


          How on earth does Integer::compareTo get resolved to a Comparator instance?



          When a method reference points to an instance method, the parser can look for methods with arity n-1 (n is the expected number of parameters).



          Here's an excerpt from the JLS on how applicable methods are identified. I will drop the first part about parsing the expression preceding the :: token.




          Second, given a targeted function type with n parameters, a set of potentially applicable methods is identified:



          If the method reference expression has the form ReferenceType :: [TypeArguments] Identifier, then the potentially applicable methods are:



          • the member methods of the type to search that would be potentially applicable (§15.12.2.1) for a method invocation which names Identifier, has arity n, has type arguments TypeArguments, and appears in the same class as the method reference expression; plus


          • the member methods of the type to search that would be potentially applicable for a method invocation which names Identifier, has arity n-1, has type arguments TypeArguments, and appears in the same class as the method reference expression.


          Two different arities, n and n-1, are considered, to account for the possibility that this form refers to either a static method or an instance method.



          ...



          A method reference expression of the form ReferenceType :: [TypeArguments] Identifier can be interpreted in different ways. If Identifier refers to an instance method, then the implicit lambda expression has an extra parameter compared to if Identifier refers to a static method.



          https://docs.oracle.com/javase/specs/jls/se12/html/jls-15.html#jls-15.13.1




          If we were to write an implicit lambda expression from that method reference, the first (implicit) parameter would be an instance to call the method on, the second (explicit) parameter would be an argument to pass in the method.



          (implicitParam, anotherInteger) -> implicitParam.compareTo(anotherInteger)


          Note that a method reference differs from a lambda expression, even though the former can be easily transformed into the latter. A lambda expression needs to be desugared into a new method, while a method reference usually requires only loading a corresponding constant method handle.




          Integer::compareTo implements Comparable interface - not Comparator.




          Integer::compareTo as an expression doesn't implement any interface. However, it can refer to/represent different functional types, one of which is Comparator<Integer>.



          Comparator<Integer> a = Integer::compareTo;
          BiFunction<Integer, Integer, Integer> b = Integer::compareTo;
          ToIntBiFunction<Integer, Integer> c = Integer::compareTo;





          share|improve this answer















          I can relate to your confusion.



          We've got a Comparator's method which declares two parameters



          int compare(T o1, T o2);


          and we've got an Integer's method which takes one parameter



          int compareTo(Integer anotherInteger)


          How on earth does Integer::compareTo get resolved to a Comparator instance?



          When a method reference points to an instance method, the parser can look for methods with arity n-1 (n is the expected number of parameters).



          Here's an excerpt from the JLS on how applicable methods are identified. I will drop the first part about parsing the expression preceding the :: token.




          Second, given a targeted function type with n parameters, a set of potentially applicable methods is identified:



          If the method reference expression has the form ReferenceType :: [TypeArguments] Identifier, then the potentially applicable methods are:



          • the member methods of the type to search that would be potentially applicable (§15.12.2.1) for a method invocation which names Identifier, has arity n, has type arguments TypeArguments, and appears in the same class as the method reference expression; plus


          • the member methods of the type to search that would be potentially applicable for a method invocation which names Identifier, has arity n-1, has type arguments TypeArguments, and appears in the same class as the method reference expression.


          Two different arities, n and n-1, are considered, to account for the possibility that this form refers to either a static method or an instance method.



          ...



          A method reference expression of the form ReferenceType :: [TypeArguments] Identifier can be interpreted in different ways. If Identifier refers to an instance method, then the implicit lambda expression has an extra parameter compared to if Identifier refers to a static method.



          https://docs.oracle.com/javase/specs/jls/se12/html/jls-15.html#jls-15.13.1




          If we were to write an implicit lambda expression from that method reference, the first (implicit) parameter would be an instance to call the method on, the second (explicit) parameter would be an argument to pass in the method.



          (implicitParam, anotherInteger) -> implicitParam.compareTo(anotherInteger)


          Note that a method reference differs from a lambda expression, even though the former can be easily transformed into the latter. A lambda expression needs to be desugared into a new method, while a method reference usually requires only loading a corresponding constant method handle.




          Integer::compareTo implements Comparable interface - not Comparator.




          Integer::compareTo as an expression doesn't implement any interface. However, it can refer to/represent different functional types, one of which is Comparator<Integer>.



          Comparator<Integer> a = Integer::compareTo;
          BiFunction<Integer, Integer, Integer> b = Integer::compareTo;
          ToIntBiFunction<Integer, Integer> c = Integer::compareTo;






          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Apr 16 at 7:10

























          answered Apr 15 at 17:51









          Andrew TobilkoAndrew Tobilko

          35.5k10 gold badges54 silver badges106 bronze badges




          35.5k10 gold badges54 silver badges106 bronze badges
























              7
















              Integer implements Comparable by overriding compareTo.



              That overriden compareTo, however, can be used in a way that satisfies and implements the Comparator interface.



              In its usage here



              int value = intList.stream().max(Integer::compareTo).get();


              it's translated to something like



              int value = intList.stream().max(new Comparator<Integer>() 
              @Override
              public int compare(Integer o1, Integer o2)
              return o1.compareTo(o2);

              ).get();


              A method reference (or lambda expression) must satisfy the signature of the corresponding functional interface's single abstract method and, in this case (Comparator), compareTo does.




              The idea is that max expects a Comparator and its compare method expects two Integer objects. Integer::compareTo can satisfy those expectations because it also expects two Integer objects. The first is its receiver (the instance on which the method is to be called) and the second is the argument. With the new Java 8 syntax, the compiler translates one style to the other.



              (compareTo also returns an int as required by Comparator#compare.)






              share|improve this answer






















              • 1





                how does Integer::compareTo satisfy the signature of Comparator#compare? compareTo(Integer) vs compare(Integer, Integer)?

                – Andrew Tobilko
                Apr 15 at 21:30







              • 1





                I disagree with "the compiler translates one style to the other". I think the compiler may validate a syntactic construct, but not translate it into another one. I am sure the compiler doesn't turn a method reference in a lambda. I didn't downvote your answer, btw.

                – Andrew Tobilko
                Apr 16 at 7:02















              7
















              Integer implements Comparable by overriding compareTo.



              That overriden compareTo, however, can be used in a way that satisfies and implements the Comparator interface.



              In its usage here



              int value = intList.stream().max(Integer::compareTo).get();


              it's translated to something like



              int value = intList.stream().max(new Comparator<Integer>() 
              @Override
              public int compare(Integer o1, Integer o2)
              return o1.compareTo(o2);

              ).get();


              A method reference (or lambda expression) must satisfy the signature of the corresponding functional interface's single abstract method and, in this case (Comparator), compareTo does.




              The idea is that max expects a Comparator and its compare method expects two Integer objects. Integer::compareTo can satisfy those expectations because it also expects two Integer objects. The first is its receiver (the instance on which the method is to be called) and the second is the argument. With the new Java 8 syntax, the compiler translates one style to the other.



              (compareTo also returns an int as required by Comparator#compare.)






              share|improve this answer






















              • 1





                how does Integer::compareTo satisfy the signature of Comparator#compare? compareTo(Integer) vs compare(Integer, Integer)?

                – Andrew Tobilko
                Apr 15 at 21:30







              • 1





                I disagree with "the compiler translates one style to the other". I think the compiler may validate a syntactic construct, but not translate it into another one. I am sure the compiler doesn't turn a method reference in a lambda. I didn't downvote your answer, btw.

                – Andrew Tobilko
                Apr 16 at 7:02













              7














              7










              7









              Integer implements Comparable by overriding compareTo.



              That overriden compareTo, however, can be used in a way that satisfies and implements the Comparator interface.



              In its usage here



              int value = intList.stream().max(Integer::compareTo).get();


              it's translated to something like



              int value = intList.stream().max(new Comparator<Integer>() 
              @Override
              public int compare(Integer o1, Integer o2)
              return o1.compareTo(o2);

              ).get();


              A method reference (or lambda expression) must satisfy the signature of the corresponding functional interface's single abstract method and, in this case (Comparator), compareTo does.




              The idea is that max expects a Comparator and its compare method expects two Integer objects. Integer::compareTo can satisfy those expectations because it also expects two Integer objects. The first is its receiver (the instance on which the method is to be called) and the second is the argument. With the new Java 8 syntax, the compiler translates one style to the other.



              (compareTo also returns an int as required by Comparator#compare.)






              share|improve this answer















              Integer implements Comparable by overriding compareTo.



              That overriden compareTo, however, can be used in a way that satisfies and implements the Comparator interface.



              In its usage here



              int value = intList.stream().max(Integer::compareTo).get();


              it's translated to something like



              int value = intList.stream().max(new Comparator<Integer>() 
              @Override
              public int compare(Integer o1, Integer o2)
              return o1.compareTo(o2);

              ).get();


              A method reference (or lambda expression) must satisfy the signature of the corresponding functional interface's single abstract method and, in this case (Comparator), compareTo does.




              The idea is that max expects a Comparator and its compare method expects two Integer objects. Integer::compareTo can satisfy those expectations because it also expects two Integer objects. The first is its receiver (the instance on which the method is to be called) and the second is the argument. With the new Java 8 syntax, the compiler translates one style to the other.



              (compareTo also returns an int as required by Comparator#compare.)







              share|improve this answer














              share|improve this answer



              share|improve this answer








              edited Apr 15 at 22:14

























              answered Apr 15 at 17:01









              SaviorSavior

              1,7482 gold badges14 silver badges34 bronze badges




              1,7482 gold badges14 silver badges34 bronze badges










              • 1





                how does Integer::compareTo satisfy the signature of Comparator#compare? compareTo(Integer) vs compare(Integer, Integer)?

                – Andrew Tobilko
                Apr 15 at 21:30







              • 1





                I disagree with "the compiler translates one style to the other". I think the compiler may validate a syntactic construct, but not translate it into another one. I am sure the compiler doesn't turn a method reference in a lambda. I didn't downvote your answer, btw.

                – Andrew Tobilko
                Apr 16 at 7:02












              • 1





                how does Integer::compareTo satisfy the signature of Comparator#compare? compareTo(Integer) vs compare(Integer, Integer)?

                – Andrew Tobilko
                Apr 15 at 21:30







              • 1





                I disagree with "the compiler translates one style to the other". I think the compiler may validate a syntactic construct, but not translate it into another one. I am sure the compiler doesn't turn a method reference in a lambda. I didn't downvote your answer, btw.

                – Andrew Tobilko
                Apr 16 at 7:02







              1




              1





              how does Integer::compareTo satisfy the signature of Comparator#compare? compareTo(Integer) vs compare(Integer, Integer)?

              – Andrew Tobilko
              Apr 15 at 21:30






              how does Integer::compareTo satisfy the signature of Comparator#compare? compareTo(Integer) vs compare(Integer, Integer)?

              – Andrew Tobilko
              Apr 15 at 21:30





              1




              1





              I disagree with "the compiler translates one style to the other". I think the compiler may validate a syntactic construct, but not translate it into another one. I am sure the compiler doesn't turn a method reference in a lambda. I didn't downvote your answer, btw.

              – Andrew Tobilko
              Apr 16 at 7:02





              I disagree with "the compiler translates one style to the other". I think the compiler may validate a syntactic construct, but not translate it into another one. I am sure the compiler doesn't turn a method reference in a lambda. I didn't downvote your answer, btw.

              – Andrew Tobilko
              Apr 16 at 7:02











              1
















              First trick: all instance methods actually take 1 additional implicit argument, the one you refer to as this in method body. E.g.:



              public final class Integer extends Number implements Comparable<Integer> 
              public int compareTo(/* Integer this, */ Integer anotherInteger)
              return compare(this.value, anotherInteger.value);



              Integer a = 10, b = 100;
              int compareResult = a.compareTo(b);
              // this actually 'compiles' to Integer#compareTo(this = a, anotherInteger = b)


              Second trick: Java compiler can "transform" the signature of a method reference to some functional interface, if the number and types of arguments (including this) satisfy:



              interface MyInterface 
              int foo(Integer bar, Integer baz);


              Integer a = 100, b = 1000;

              int result1 = ((Comparator<Integer>) Integer::compareTo).compare(a, b);
              int result2 = ((BiFunction<Integer, Integer, Integer>) Integer::compareTo).apply(a, b);
              int result3 = ((MyInterface) Integer::compareTo).foo(a, b);

              // result1 == result2 == result3


              As you can see class Integer implements none of Comparator, BiFunction or a random MyInterface, but that doesn't stop you from casting the Integer::compareTo method reference as those interfaces.






              share|improve this answer































                1
















                First trick: all instance methods actually take 1 additional implicit argument, the one you refer to as this in method body. E.g.:



                public final class Integer extends Number implements Comparable<Integer> 
                public int compareTo(/* Integer this, */ Integer anotherInteger)
                return compare(this.value, anotherInteger.value);



                Integer a = 10, b = 100;
                int compareResult = a.compareTo(b);
                // this actually 'compiles' to Integer#compareTo(this = a, anotherInteger = b)


                Second trick: Java compiler can "transform" the signature of a method reference to some functional interface, if the number and types of arguments (including this) satisfy:



                interface MyInterface 
                int foo(Integer bar, Integer baz);


                Integer a = 100, b = 1000;

                int result1 = ((Comparator<Integer>) Integer::compareTo).compare(a, b);
                int result2 = ((BiFunction<Integer, Integer, Integer>) Integer::compareTo).apply(a, b);
                int result3 = ((MyInterface) Integer::compareTo).foo(a, b);

                // result1 == result2 == result3


                As you can see class Integer implements none of Comparator, BiFunction or a random MyInterface, but that doesn't stop you from casting the Integer::compareTo method reference as those interfaces.






                share|improve this answer





























                  1














                  1










                  1









                  First trick: all instance methods actually take 1 additional implicit argument, the one you refer to as this in method body. E.g.:



                  public final class Integer extends Number implements Comparable<Integer> 
                  public int compareTo(/* Integer this, */ Integer anotherInteger)
                  return compare(this.value, anotherInteger.value);



                  Integer a = 10, b = 100;
                  int compareResult = a.compareTo(b);
                  // this actually 'compiles' to Integer#compareTo(this = a, anotherInteger = b)


                  Second trick: Java compiler can "transform" the signature of a method reference to some functional interface, if the number and types of arguments (including this) satisfy:



                  interface MyInterface 
                  int foo(Integer bar, Integer baz);


                  Integer a = 100, b = 1000;

                  int result1 = ((Comparator<Integer>) Integer::compareTo).compare(a, b);
                  int result2 = ((BiFunction<Integer, Integer, Integer>) Integer::compareTo).apply(a, b);
                  int result3 = ((MyInterface) Integer::compareTo).foo(a, b);

                  // result1 == result2 == result3


                  As you can see class Integer implements none of Comparator, BiFunction or a random MyInterface, but that doesn't stop you from casting the Integer::compareTo method reference as those interfaces.






                  share|improve this answer















                  First trick: all instance methods actually take 1 additional implicit argument, the one you refer to as this in method body. E.g.:



                  public final class Integer extends Number implements Comparable<Integer> 
                  public int compareTo(/* Integer this, */ Integer anotherInteger)
                  return compare(this.value, anotherInteger.value);



                  Integer a = 10, b = 100;
                  int compareResult = a.compareTo(b);
                  // this actually 'compiles' to Integer#compareTo(this = a, anotherInteger = b)


                  Second trick: Java compiler can "transform" the signature of a method reference to some functional interface, if the number and types of arguments (including this) satisfy:



                  interface MyInterface 
                  int foo(Integer bar, Integer baz);


                  Integer a = 100, b = 1000;

                  int result1 = ((Comparator<Integer>) Integer::compareTo).compare(a, b);
                  int result2 = ((BiFunction<Integer, Integer, Integer>) Integer::compareTo).apply(a, b);
                  int result3 = ((MyInterface) Integer::compareTo).foo(a, b);

                  // result1 == result2 == result3


                  As you can see class Integer implements none of Comparator, BiFunction or a random MyInterface, but that doesn't stop you from casting the Integer::compareTo method reference as those interfaces.







                  share|improve this answer














                  share|improve this answer



                  share|improve this answer








                  edited Apr 16 at 18:35

























                  answered Apr 16 at 18:20









                  TairTair

                  3,13414 silver badges29 bronze badges




                  3,13414 silver badges29 bronze badges































                      draft saved

                      draft discarded















































                      Thanks for contributing an answer to Stack Overflow!


                      • Please be sure to answer the question. Provide details and share your research!

                      But avoid


                      • Asking for help, clarification, or responding to other answers.

                      • Making statements based on opinion; back them up with references or personal experience.

                      To learn more, see our tips on writing great answers.




                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function ()
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55694015%2fjava-8-stream-max-function-argument-type-comparator-vs-comparable%23new-answer', 'question_page');

                      );

                      Post as a guest















                      Required, but never shown





















































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown

































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown







                      Popular posts from this blog

                      Distance measures on a map of a game The 2019 Stack Overflow Developer Survey Results Are Inmin distance in a graphShortest distance path on contour plotHow to plot a tilted map?Finding points outside of a diskDelaunay link distanceAnnulus from GeoDisks: drawing a ring on a mapNegative Correlation DistanceFind distance along a path (GPS coordinates)Finding position at given distance in a GeoPathMathematics behind distance estimation using camera

                      How to get a smooth, uniform ParametricPlot of a 2D Region?How to plot a complicated Region?How to exclude a region from ParametricPlotHow discretize a region placing vertices on a specific non-uniform gridHow to transform a Plot or a ParametricPlot into a RegionHow can I get a smooth plot of a bounded region?Smooth ParametricPlot3D with RegionFunction?Smooth border of a region ParametricPlotSmooth region boundarySmooth region plot from list of pointsGet minimum y of a certain x in a region

                      Genealogie vun de Merowenger Vum Merowech bis zum Chilperich I. | Navigatiounsmenü