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)
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);
}
}
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.
u can use one of these 2 methods to compare Double
listOfDouble.stream().max(Double::compareTo);
listOfDouble.stream().max(Comparator.naturalOrder());