Java 为什么可以将Double::compareTo用作Stream.max(Comparator<;?super T>;Comparator)的参数

Java 为什么可以将Double::compareTo用作Stream.max(Comparator<;?super T>;Comparator)的参数,java,java-8,java-stream,comparator,method-reference,Java,Java 8,Java Stream,Comparator,Method Reference,Stream.max的api需要类型为Comparator的参数u可以使用这两种方法之一来比较Double listOfDouble.stream().max(Double::compareTo); listOfDouble.stream().max(Comparator.naturalOrder()); 看看甲骨文。这是对实例方法的引用。这意味着,它可以被视为双函数,将实例作为第一个参数 在(15.13.3)中,我们可以看到: 如果表单是ReferenceType::[TypeArgumen

Stream.max
的api需要类型为
Comparator的参数u可以使用这两种方法之一来比较Double

listOfDouble.stream().max(Double::compareTo);
listOfDouble.stream().max(Comparator.naturalOrder());
看看甲骨文。这是对实例方法的引用。这意味着,它可以被视为
双函数
,将实例作为第一个参数

在(15.13.3)中,我们可以看到:

如果表单是ReferenceType::[TypeArguments]Identifier,则调用方法的主体对于编译时声明(即方法引用表达式的编译时声明)具有类似的方法调用表达式的效果。方法调用表达式的运行时评估如§15.12.4.3、§15.12.4.4和§15.12.4.5所述,其中:

  • 调用模式源自§15.12.3中规定的编译时声明

  • 如果编译时声明是实例方法,则目标引用是调用方法的第一个形式参数。否则,没有目标引用

  • 如果编译时声明是实例方法,那么方法调用表达式(如果有)的参数是调用方法的第二个和后续形式参数。否则,方法调用表达式的参数就是调用方法的形式参数


有趣的部分由我加粗。

下面的
MyComparator
实现了一个
比较器。它需要两个参数。
它与lambda表达式
(d1,d2)->d1相同。与(d2)

与方法参考相同
Double::compareTo

方法引用是相同的,因为
d1
是一个
Double
,所以Java假设在第一个
Double
上调用
compareTo
方法。另一个参数
d2
成为所调用方法的参数。这也被@Andronicus很好地解释了

本例中的3种变体是等效的:

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);
   }
}
import java.util.List;
导入java.util.Comparator;
类MyComparator实现比较器{
公共整数比较(双d1,双d2){/(d1,d2)->
返回d1.compareTo(d2);//d1.compareTo(d2)
}
}
公共类测试{
公共静态void main(字符串[]args){
列表=列表(1.1,2.2,3.3,4.4,5.5,6.6,7.7);
双最大类=
list.stream()
.max(新的MyComparator())
.orElse(双负无穷大);
双maxLamdba=
list.stream()
.max((d1,d2)->d1.与(d2)相比)
.orElse(双负无穷大);
双maxMethodreference=
list.stream()
.max(双::比较)
.orElse(双负无穷大);
}
}

我发现streamObj.max(Double::compareTo)可以成功运行您选择了错误答案作为正确答案。这基本上是一个“我也是”的答案,是安德洛尼卡提供的第一个正确答案。@hoverfullofeels我理解你的立场。当我了解它的时候,我很难理解它。参考语言规范给出的答案很好,但在我努力解决它时,它对我没有帮助。对不起,我不明白..Double::compareTo是一种实例方法吗?什么是“目标引用是调用方法的第一个形式参数…”意味着什么?它不是静态方法,而是在实例上调用的,因此是“引用实例方法”。第二个问题-引用方法相当于
(d,otherD)->d.compareTo(otherD)
,这意味着调用该方法的实例是
双功能的第一个参数。我希望clearOP知道可以使用
compareTo
,问题是为什么可以使用它,一个需要一个参数的方法,当需要一个
比较器时,其(函数)方法需要两个参数
Optional<T> max(Comparator<? super T> comparator)
listOfDouble.stream().max(Double::compareTo);
listOfDouble.stream().max(Comparator.naturalOrder());
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);
   }
}