【问题标题】:Why Double::compareTo can be used as an argument of Stream.max(Comparator<? super T> comparator)为什么 Double::compareTo 可以用作 Stream.max(Comparator<? super T> 比较器) 的参数
【发布时间】:2020-02-15 15:12:41
【问题描述】:

Stream.max 的 api 需要 Comparator&lt;? super T&gt; 类型的参数,而对于 Comparator,唯一的抽象方法是

int compare(T o1, T o2)

但是Double::compareTocompareTo api 是

public int compareTo(Double anotherDouble)

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

Optional<T> max(Comparator<? super T> comparator)

【问题讨论】:

  • 我发现streamObj.max(Double::compareTo) 可以成功运行
  • 您选择了错误答案作为正确答案。它基本上是 Andronicus 提供的第一个正确答案的“我也是”答案。
  • @HovercraftFullOfEels 我理解你的立场。当我学习它时,我很难理解这一点。参考语言规范给出的答案很好,但是当我努力解决它时它对我没有帮助。

标签: java java-8 java-stream comparator method-reference


【解决方案1】:

查看预言机documentation。这是对 instance 方法的引用。这意味着,它可以被认为是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 中指定的编译时声明。

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

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

有趣的部分被我加粗了。

【讨论】:

  • 对不起但不明白..Double::compareTo 是实例方法吗? “目标引用是调用方法的第一个形参……”是什么意思?
  • 它不是静态方法,它是在实例上调用的,因此是“引用实例方法”。而第二个问题——引用方法等价于(d, otherD) -&gt; d.compareTo(otherD),也就是说,调用该方法的实例是BiFunction的第一个参数。我希望它很清楚
【解决方案2】:

下面的MyComparator 实现了Comparator。它需要两个参数。
与 lambda 表达式 (d1,d2) -&gt; d1.compareTo(d2)
相同 和方法参考Double::compareTo一样

方法引用是相同的,因为d1Double,所以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);
   }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-07-16
    • 1970-01-01
    • 2019-07-14
    • 2017-10-07
    • 2016-01-05
    • 2021-09-04
    • 2011-02-13
    相关资源
    最近更新 更多