简体   繁体   English

如何在 Scala 中使用 Java lambda

[英]How to use Java lambdas in Scala

I have the following code:我有以下代码:

source
    .mapValues(value -> value + " Stream it!!!")
    .print(Printed.toSysOut());

as you can see, mapValues expects a lambda expression.如您所见, mapValues需要一个 lambda 表达式。

Now, I am using Java library but the application is written in Scala.现在,我正在使用 Java 库,但应用程序是用 Scala 编写的。 How to pass Scala lambda to Java code?如何将 Scala lambda 传递给 Java 代码?

I tried the following:我尝试了以下方法:

source
  .mapValues(value => value + "hello")
  .print(Printed.toSysOut)

But the compiler complains:但是编译器抱怨:

[error]   (x$1: org.apache.kafka.streams.kstream.Printed[String,?0(in value x$1)])Unit <and>
[error]   (x$1: org.apache.kafka.streams.kstream.KeyValueMapper[_ >: String, _ >: ?0(in value x$1), String])Unit <and>
[error]   (x$1: String)Unit
[error]  cannot be applied to (org.apache.kafka.streams.kstream.Printed[Nothing,Nothing])
[error]       .print(Printed.toSysOut)
[error]        ^
[error] two errors found
[error] (compile:compileIncremental) Compilation failed
[error] Total time: 2 s, completed Nov 19, 2017 7:53:44 PM

It depends on your version of Scala.这取决于您的 Scala 版本。

In 2.12 Scala functions can be used in places where Java functions are expected and vice versa.在 2.12 中,Scala 函数可用于需要 Java 函数的地方,反之亦然。

App1.java应用程序1.java

import java.util.function.Function;

public class App1 {
    public static void method(Function<String, String> function) {
        System.out.println(function.apply("a"));
    }

    public static void main(String[] args) {
        App.method1((String s) -> s.toUpperCase());
    }
}

App.scala应用程序

object App {
  def main(args: Array[String]): Unit = {
    App1.method((s: String) => s.toUpperCase)
  }

  def method1(function: String => String): Unit = {
    println(function("xyz"))
  }
}

In 2.11 you can use scala-java8-compat在 2.11 你可以使用scala-java8-compat

libraryDependencies += "org.scala-lang.modules" %% "scala-java8-compat" % "0.8.0"

App1.java应用程序1.java

import java.util.function.Function;
import static scala.compat.java8.JFunction.func;

public class App1 {
    public static void method(Function<String, String> function) {
        System.out.println(function.apply("a"));
    }

    public static void main(String[] args) {
        App.method1(func((String s) -> s.toUpperCase()));
    }
}

App.scala应用程序

import scala.compat.java8.FunctionConverters._

object App {
  def main(args: Array[String]): Unit = {
    App1.method(((s: String) => s.toUpperCase).asJava)
  }

  def method1(function: String => String): Unit = {
    println(function("xyz"))
  }
}

Alternatively in 2.11 in Scala you can define implicit converters between java.util.function.Function and scala.Function1 .或者,在 Scala 的 2.11 中,您可以在java.util.function.Functionscala.Function1之间 定义隐式转换器

So if you use 2.11 try所以如果你使用 2.11 试试

source
  .mapValues((value => value + "hello").asJava)
  .print(Printed.toSysOut) 

or或者

source
  .mapValues(((value: String) => value + "hello").asJava)
  .print(Printed.toSysOut[String, String])

The error message lists the types of arguments that print supports.错误消息列出了print支持的参数类型。 One of them is:其中之一是:

org.apache.kafka.streams.kstream.Printed[String,?0(in value x$1)]

From the error message you can see that you're providing Printed.toSysOut with a type of:从错误消息中,您可以看到您提供的Printed.toSysOut类型为:

org.apache.kafka.streams.kstream.Printed[Nothing,Nothing]

According to the Kafka 1 javadoc ( Printed was not present in Kafka 1.1), toSysOut is defined as: 根据 Kafka 1 javadoc (在 Kafka 1.1 中不存在Printed ), toSysOut定义为:

public static <K,V> Printed<K,V> toSysOut()

So the answer problem is that Scala is inferring K and V with types of Nothing .所以答案问题是 Scala 推断KV类型为Nothing You need to provide the types explicitly.您需要明确提供类型。

The following will probably work:以下可能会起作用:

source
  .mapValues[String](value -> value + " Stream it!!!")
  .print(Printed.toSysOut[String,String])

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM