Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why Double::compareTo can be used as an argument of Stream.max(Comparator<? super T> comparator)

The api for Stream.max requires an argument of type Comparator<? super T>, and for Comparator, the only abstract method is

int compare(T o1, T o2)

but Double::compareTo, the compareTo api is

public int compareTo(Double anotherDouble)

why just provide one argument, so why can Double::compareTo use as argument of Stream

Optional<T> max(Comparator<? super T> comparator)
like image 909
user1169587 Avatar asked Dec 18 '22 14:12

user1169587


2 Answers

Check out the oracle documentation. This is a reference to an instance method. This means, it can be considered as BiFunction, that takes the instance as the first argument.

In Java Language Specification (15.13.3) we can read, that:

If the form is ReferenceType :: [TypeArguments] Identifier, the body of the invocation method similarly has the effect of a method invocation expression for a compile-time declaration which is the compile-time declaration of the method reference expression. Run-time evaluation of the method invocation expression is as specified in §15.12.4.3, §15.12.4.4, and §15.12.4.5, where:

  • The invocation mode is derived from the compile-time declaration as specified in §15.12.3.

  • If the compile-time declaration is an instance method, then the target reference is the first formal parameter of the invocation method. Otherwise, there is no target reference.

  • If the compile-time declaration is an instance method, then the arguments to the method invocation expression (if any) are the second and subsequent formal parameters of the invocation method. Otherwise, the arguments to the method invocation expression are the formal parameters of the invocation method.

The interesting part is bolded by me.

like image 60
Andronicus Avatar answered Apr 26 '23 23:04

Andronicus


The below MyComparator implement a Comparator. It takes two arguments.
It's the same as the lambda expression (d1,d2) -> d1.compareTo(d2)
and the same as the method reference Double::compareTo

The method reference is the same because d1 is a Double, so Java assumes the compareTo method is to be called on the first Double. The other argument d2 becomes the argument for the method called. This is also very nicely explained by @Andronicus.

The 3 variants in this example are equivalent:

import java.util.List;
import java.util.Comparator;

class MyComparator implements Comparator<Double> {
  public int compare(Double d1, Double d2) {    // (d1,d2) ->
    return d1.compareTo(d2);                    // d1.compareTo(d2)
  }
}

public class Testing {
    public static void main(String[] args) {
      List<Double> list = List.of(1.1,2.2,3.3,4.4,5.5,6.6,7.7);

      Double maxClass =
        list.stream()
            .max(new MyComparator())
            .orElse(Double.NEGATIVE_INFINITY);

      Double maxLamdba =
        list.stream()
            .max((d1,d2) -> d1.compareTo(d2))
            .orElse(Double.NEGATIVE_INFINITY);

      Double maxMethodreference =
        list.stream()
            .max(Double::compareTo)
            .orElse(Double.NEGATIVE_INFINITY);
   }
}
like image 44
Scratte Avatar answered Apr 27 '23 01:04

Scratte