将Scala函数传递给Java 8方法


18

以下Scala代码可以正常工作,并且可以传递给需要功能的Java方法。有没有更清洁的方法可以做到这一点?这是我的第一遍:

val plusOne = new java.util.function.Function[Int,Int] {
  override def apply(t:Int):Int = t + 1

  override def andThen[V](after:function.Function[_ >: Int, _ <: V]):
    function.Function[Int, V] = ???

  override def compose[V](before:function.Function[_ >: V, _ <: Int]):
    function.Function[V, Int] = ???
}

这是我的第二遍-它使用Java-8 Function接口的通用包装器来简化Scala语法:

// Note: Function1 is Scala's functional interface,
// Function (without the 1) is Java 8's.
case class JavaFunction1[U,V](f:Function1[U,V]) extends Function[U,V] {
  override def apply(t: U): V = f(t)
  override def compose[T](before:Function[_ >: T, _ <: U]):
    Function[T, V] = ???
  override def andThen[W](after:Function[_ >: V, _ <: W]):
    Function[U, W] = ???
}

val plusOne = JavaFunction1((x:Int) => x + 1)
val minusOne = JavaFunction1((x:Int) => x - 1)

我们可以做得更好吗?

作为后续措施,Scala有一天有可能像Java 8一样使用一流的动态函数操作调用动态操作代码吗?这将使一切神奇地起作用,还是仍然需要进行语法转换?

Answers:


10

您可以使转换隐式:

implicit def toJavaFunction[U, V](f:Function1[U,V]): Function[U, V] = new Function[U, V] {
  override def apply(t: U): V = f(t)

  override def compose[T](before:Function[_ >: T, _ <: U]):
    Function[T, V] = toJavaFunction(f.compose(x => before.apply(x)))

  override def andThen[W](after:Function[_ >: V, _ <: W]):
    Function[U, W] = toJavaFunction(f.andThen(x => after.apply(x)))
}

implicit def fromJavaFunction[U, V](f:Function[U,V]): Function1[U, V] = f.apply

您实际上不需要覆盖composeandThen,但是Scala编译器可能还不了解Java 8默认接口方法。(编辑:它应该在2.10.3中工作。)

此外,您应该能够将Scala lambda(即x => ...)分配给FunctionScala 2.11和其他任何SAM类型,而将Java 8 lambda分配给Function1。(编辑:这实际上是在Scala 2.12,而不是2.11中添加的。)


you should be able to assign Scala lambdas-这意味着在Scala 2.11中,可以将Scala函数作为Java8 Lambda的参数传递?
凯文·梅瑞迪斯

是否可以将其作为参数传递取决于lambda的类型。如果java.util.function.Consumer[scala.Function1[Integer, String]]是这样,那么它也可以在2.11之前完成。
阿列克谢·罗曼诺夫
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.