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

use*_*587 4 java comparator java-8 java-stream method-reference

api forStream.max需要一个类型的参数Comparator<? super T>,而 for Comparator,唯一的抽象方法是

int compare(T o1, T o2)
Run Code Online (Sandbox Code Playgroud)

但是Double::compareTocompareToapi是

public int compareTo(Double anotherDouble)
Run Code Online (Sandbox Code Playgroud)

为什么只提供一个参数,那么为什么可以Double::compareTo用作 Stream 的参数

Optional<T> max(Comparator<? super T> comparator)
Run Code Online (Sandbox Code Playgroud)

And*_*cus 9

查看 oracle文档。这是对实例方法的引用。这意味着,它可以被视为BiFunction,将实例作为第一个参数。

Java Language Specification (15.13.3) 中,我们可以读到:

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

  • 调用模式源自第 15.12.3 节中指定的编译时声明。

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

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

有趣的部分是我加粗的。

  • 它不是静态方法,它是在实例上调用的,因此是“对实例方法的引用”。第二个问题 - 引用方法相当于 `(d, otherD) -&gt; d.compareTo(otherD)`,这意味着调用该方法的实例是 `BiFunction` 的第一个参数。我希望它是清楚的 (2认同)

Scr*_*tte 2

下面MyComparator实现一个Comparator. 它需要两个参数。
与 lambda 表达式相同(d1,d2) -> d1.compareTo(d2)
,与方法引用相同Double::compareTo

方法引用是相同的,因为d1都是 a Double,因此 Java 假定该compareTo方法将在第一个上调用Double。另一个参数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);
   }
}
Run Code Online (Sandbox Code Playgroud)