Scala如何总结一份期货清单

时间:2015-06-11 21:54:44

标签: scala

我已编写此代码并且可以正常使用

import scala.concurrent.{Future}
import scala.concurrent.ExecutionContext.Implicits.global
import scala.util.{Failure, Success, Random}

object TestFuture2 {
  def bigCalc() : Future[Int] = Future {
    Thread.sleep(1000)
    40
  }
}

object Main2 extends App {
  val x = TestFuture2.bigCalc
  val y = TestFuture2.bigCalc
  val z = TestFuture2.bigCalc

  val v = for {
    r1 <- x
    r2 <- y
    r3 <- z
  } yield (r1 + r2 + r3)

  v onSuccess {
    case x1 => println(x1)
  }
  System.in.read()
}

所以当我跑这个时,我得到120.好。

但我不喜欢我在for循环中总结值

for {
  r1 <- x
  r2 <- y
  r3 <- z
} yield (r1 + r2 + r3)

如果我调用我的函数

,该怎么办?
val x = List(TestFuture2.bigCalc, TestFuture2.bigCalc, TestFuture2.bigCalc, TestFuture2.bigCalc, TestFuture2.bigCalc)

现在我将如何总结?

我试过

x.reduce(_ + _)

但这不起作用。

scala> x.reduce(_ + _)
<console>:17: error: type mismatch;
 found   : scala.concurrent.Future[Int]
 required: String
              x.reduce(_ + _)

3 个答案:

答案 0 :(得分:9)

Future.sequenceTraversable[Future[T]]转换为Future[Traversable[T]](如果原始列表中的任何期货失败,则此未来将失败)。之后,您只需拨打sum关于此未来的内容:

Future.sequence(x).map(_.sum)

答案 1 :(得分:2)

TL; DR 使用:Future.reduce(futures)(_ + _)

您的代码示例的主要问题是Traversable#reduceFuture#reduce之间的混淆。你想使用第二个,但你使用第一个。

Traversable#reduce需要具有此签名的缩减功能:Tuple2[Future[Int], Future[Int]] => Future[Int]

另一方面,Future#reduce将自动解包存储在期货中的值。它需要具有此签名的缩减功能:Tuple2[Int, Int] => Int。更实际。

使用Traversable#reduce函数的示例:

val futures = List(TestFuture2.bigCalc, TestFuture2.bigCalc, TestFuture2.bigCalc, TestFuture2.bigCalc, TestFuture2.bigCalc)
val reduced = futures.reduce((first: Future[Int], second: Future[Int]) => first.flatMap(firstResult => second.map(secondResult => secondResult + firstResult)))

使用Future#reduce函数的示例:

val futures = List(TestFuture2.bigCalc, TestFuture2.bigCalc, TestFuture2.bigCalc, TestFuture2.bigCalc, TestFuture2.bigCalc)
val reduced = Future.reduce(futures)((first: Int, second: Int) => first + second)

您可以直接使用Future#sequence,因为这是Future#reduce在幕后使用它的内容。但是你为什么要使用后者呢?如果列表为空,它将返回将来的失败。因此,使用其中一个取决于您的要求。如果列表永远不应为空,请使用Future#reduce

答案 2 :(得分:1)

如果你想使用reduce,你可以这样做。

  list.reduce((future1, future2) =>
      future1.zip(future2).map(pair => pair._1 + pair._2))
    .onComplete({ case Success(value) => println(value)})