返回 Future[(Int,Int)] 而不是 (Future[Int],Future[Int]) [英] Return Future[(Int,Int)] instead of (Future[Int],Future[Int])

查看:54
本文介绍了返回 Future[(Int,Int)] 而不是 (Future[Int],Future[Int])的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下期货:

def f1 = Future {1}    
def f2 = Future {2}

我需要以下代码来返回 Future[(Int,Int)] :

I need the following code to return Future[(Int,Int)] :

val future = // function that returns a future
future.flatMap {
    val x1 = f1
    val x2 = f2
    (x1,x2)  // This returns Future[Int],Future[Int] 
}

代替 (Future[Int],Future[Int]) 我需要返回 Future[(Int,Int)] 的函数.如何转换它?

Instead of (Future[Int],Future[Int]) I need the function to return Future[(Int,Int)]. How to convert it?

推荐答案

我将在此处对(当前)已接受的答案提出异议.根据我的评论,这并不是将两个未来压缩在一起的正确方式.正确的方法很简单:

I'm going to take issue with the (currently) accepted answer here. As per my comment, this is not really the correct way to zip together two futures. the correct way is simply this:

f1 zip f2

另一个答案:

for (x <- f1; y <- f2) yield (x, y)

虽然这会起作用,但在 f2 是产生未来的表达式的情况下并不平行(就像在这个问题中一样).如果是这种情况,在第一个未来完成[1]之前不会构建f2.虽然 zip 已经在 flatMap 方面以同样的方式实现,因为它的参数是严格的,第二个 future 已经在运行(当然取决于执行上下文).

Whilst this will work, it is not parallel in the case that f2 is an expression yielding a future (as it is in this question). If this is the case, f2 will not be constructed until the first future has completed [1]. Whilst zip has been implemented in terms of flatMap in the same way, because its argument is strict, the second future is already running (subject to the execution context of course).

它也更简洁!

[1] - 这可以通过观察 y(由 f1 计算出的值)在 的范围内而看出f2被构造

[1] - this can be seen by observing that y, the value computed by f1, is in scope as f2 is constructed

这很容易证明:

scala> import scala.concurrent._; import ExecutionContext.Implicits.global
import scala.concurrent._
import ExecutionContext.Implicits.global

scala> def createAndStartFuture(i: Int): Future[Int] = Future {
     |   println(s"starting $i in ${Thread.currentThread.getName} at ${java.time.Instant.now()}")
     |   Thread.sleep(20000L)
     |   i
     | }
createAndStartFuture: (i: Int)scala.concurrent.Future[Int]

有了这个:

scala> for (x <- createAndStartFuture(1); y <- createAndStartFuture(2)) yield (x, y)
starting 1 in scala-execution-context-global-34 at 2017-05-05T10:29:47.635Z
res15: scala.concurrent.Future[(Int, Int)] = Future(<not completed>)

// Waits 20s
starting 2 in scala-execution-context-global-32 at 2017-05-05T10:30:07.636Z

但是带拉链

scala> createAndStartFuture(1) zip createAndStartFuture(2)
starting 1 in scala-execution-context-global-34 at 2017-05-05T10:30:45.434Z
starting 2 in scala-execution-context-global-32 at 2017-05-05T10:30:45.434Z
res16: scala.concurrent.Future[(Int, Int)] = Future(<not completed>)

这篇关于返回 Future[(Int,Int)] 而不是 (Future[Int],Future[Int])的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆