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

◇◆丶佛笑我妖孽 提交于 2020-06-25 04:42:13

问题


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)

回答1:


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);
   }
}



回答2:


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.




回答3:


u can use one of these 2 methods to compare Double

listOfDouble.stream().max(Double::compareTo);
listOfDouble.stream().max(Comparator.naturalOrder());


来源:https://stackoverflow.com/questions/60240046/why-doublecompareto-can-be-used-as-an-argument-of-stream-maxcomparator-supe

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!