使用scala.Future和Java 8 lambda表达式

7

Scala的Future类有多个基于函数式编程的方法。当从Java中调用时,使用Java 8的lambda表达式似乎是一个自然的选择。

然而,当我尝试实际使用它时,遇到了几个问题。以下代码无法编译:

someScalaFuture.map(val -> Math.sqrt(val)).
       map(val -> val + 3); 

因为map函数需要一个隐式的ExecutionContext参数。在Scala中,你通常可以忽略这一点,但在Java中需要显式传递。

someScalaFuture.map(val -> Math.sqrt(val),
                    ec).
       map(val -> val + 3,
           ec);

这会导致以下错误:

error: method map in interface Future<T> cannot be applied to given types;
[ERROR] val),ExecutionContextExecutor
  reason: cannot infer type-variable(s) S
    (argument mismatch; Function1 is not a functional interface
      multiple non-overriding abstract methods found in interface Function1)
  where S,T are type-variables:
    S extends Object declared in method <S>map(Function1<T,S>,ExecutionContext)
    T extends Object declared in interface Future 

如果我创建了一个继承Function1的匿名类,并实现apply方法如下:
    someScalaFuture.map(new Function1<Double, Double>() {
            public double apply(double val) { return Math.sqrt(val); }
        },
        ec).
        map(val -> val + 3,
            ec);

我收到一个错误信息,内容为:
error: <anonymous com.example.MyTestClass$1> is not abstract and does not override abstract method apply$mcVJ$sp(long) in Function1

我没有尝试实现这种方法(也不确定是否可以在名称中间使用美元符号实现方法),但这似乎是我开始探讨Scala实现的细节。

我走的路径可行吗?有没有合理的方法以这种方式使用lambda表达式?如果有一个可以使这个工作的库,那么这是一个可接受的解决方案。理想情况下,像这样的东西

import static org.thirdparty.MakeLambdasWork.wrap;
...
   wrap(someScalaFuture).map(val -> Math.sqrt(val)).
         map(val -> val + 3);

你尝试使用哪个版本的Scala来完成这个呢? - childofsoong
我正在使用Scala 2.11。 - Troy Daniels
2个回答

4

Scala-java8-compat 库提供了 Scala 2.11 和 Java 8 lambda 表达式之间的互操作性。


4

正如 @Seth 提到的,你可以使用 scala-java8-compat

import scala.concurrent.Future;
import static scala.compat.java8.FutureConverters.globalExecutionContext;
import static scala.compat.java8.JFunction.func;
...

Future<Object> future = ...;

future.onComplete(
    func(x -> ...), /// wraps Java lambda into a Scala Function
    globalExecutionContext());// Gets the global execution context.

然而,Scala 2.12引入了一些特性,使其更加兼容Java,现在你可以直接使用lambda函数。
Future<Object> future = ...;

future.onComplete(
    x -> ..., // Uses Java lambda directly
    globalExecutionContext()); // Gets the global execution context.

ExecutionContext.global 基本上是由 ForkJoinPool 支持的执行上下文,管理有限数量的线程。

如果您需要获取更多信息,我建议查看以下两个链接:

Futures 中的执行上下文

当不确定时,请坚持使用 scala.concurrent.ExecutionContext.global


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接