Scala类型检查抱怨lambda,而不是显式函数

zal*_*ale 5 scala

我有以下Scala代码:

import java.util.{Comparator, function}

object ComparatorTest {
  Comparator.comparing[Int, String](new function.Function[Int, String] {
    override def apply(t: Int): String = t.toString
  })
}
Run Code Online (Sandbox Code Playgroud)

编译没有问题.我想我应该能够Function用lambda 替换它(这是我从文档中理解的,至少,IntelliJ是相同的意见).但是,当我用它替换它

  Comparator.comparing[Int, String]((t: Int) ? t.toString)
Run Code Online (Sandbox Code Playgroud)

我收到编译器错误:

Error:(6, 23) overloaded method value comparing with alternatives:
  (x$1: java.util.function.Function[_ >: Int, _ <: String])java.util.Comparator[Int] <and>
  (x$1: java.util.function.Function[_ >: Int, _ <: String],x$2: java.util.Comparator[_ >: String])java.util.Comparator[Int]
 cannot be applied to (Int => String)
  Comparator.comparing[Int, String]((t: Int) ? t.toString)
Run Code Online (Sandbox Code Playgroud)

(在我看来,第一种选择应该匹配.)

我刚刚问了一个类似的问题,解决方法是明确指定类型参数,但在这种情况下,我认为我已经指定了我能做的一切.是否有另一种使用lambda的解决方案,或者是否需要明确Function需要?如果是后者,是否有一个文档解释了什么时候lambda可以替代SAM?

Bri*_*hon 5

TL; DR:使用Ordering而不是Comparator直接使用.


您可以使用类型归属来强制它将您的参数识别为java.util.function.Function[Int, String]:

Comparator.comparing[Int, String]((_.toString) : function.Function[Int, String])
Run Code Online (Sandbox Code Playgroud)

请注意,周围的括号_.toString是必需的; 否则,它会尝试将ascription应用于lambda中的表达式而不是lambda作为整体.此代码基本上等同于:

val tmp: function.Function[Int, String] = _.toString
Comparator.comparing[Int, String](tmp)
Run Code Online (Sandbox Code Playgroud)

但是,在编写Scala时,通常更好用Ordering.自Ordering扩展以来Comparator,它可以在任何Comparator预期的地方使用.您可以使用它:

val cmp: Comparator[Int] = Ordering.by(_.toString)
Run Code Online (Sandbox Code Playgroud)

要么:

val cmp = Ordering.by[Int, String](_.toString)
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,类型推断在这里工作得更好.