Scala 根据未来的运营情况保留金额

Scala 根据未来的运营情况保留金额,scala,Scala,目标是遍历对列表中的每个元素执行未来操作的列表,然后对这些未来操作返回的值求和 我试图只使用不可变的数据 大概是这样的: list.foldRight(0)((obj,sum) => { val c: Int = doFutureThing(obj) c + sum // no good: c is a Future[Int] } 尝试使用类似的方法: import scala.concurrent.duration.Duration import scala.concurre

目标是遍历对列表中的每个元素执行未来操作的列表,然后对这些未来操作返回的值求和

我试图只使用不可变的数据

大概是这样的:

list.foldRight(0)((obj,sum) => {
  val c: Int = doFutureThing(obj)
  c + sum  // no good: c is a Future[Int]
}

尝试使用类似的方法:

import scala.concurrent.duration.Duration
import scala.concurrent.{Await, Future}
import scala.concurrent.ExecutionContext.Implicits.global

object Scratch {
  def operation(i: Int): Future[Int] = {
    Future.successful(i+1)
  }

  def main(args: Array[String]) {
    val list = List(1,2,3,4)
    val resultFuture = Future
      .sequence(list.map(operation))
      .transform(list => list.foldLeft(0)((x, y) => x+y), t => t)
    println(Await.result(resultFuture, Duration.Inf))
  }
}
这里发生了什么:

  • 关键思想是
    Future.sequence
    。它允许您将期货集合转换为集合的未来,然后以常规方式操作该集合。所以我们用它来简化我们的工作。现在我们有了
    Future[List[Int]]
    而不是
    List[Future[Int]]
  • 我们使用
    transform
    方法将我们的
    Future[List[Int]]
    映射到
    Future[Int]
    。实际上,这里我们可以使用任何我们想要的转换,而不仅仅是计算和
  • 我们等待使用隐式默认执行上下文的
    Future[Int]
    的结果

  • 如果您的源集合非常大,因此它不能适合您的堆,并且您希望在准备好足够的Int未来时应用操作(假设操作顺序不重要),那么这种方法的唯一问题可能会出现。如果您希望这样做,答案应该更复杂一些。

    如果您从一组项目开始

    val li = List(2, 4, 7)  // List[Int]
    
    …然后将其转换为一个未来的集合

    import concurrent._
    import concurrent.ExecutionContext.Implicits.global
    val lfi = li.map(doFutureThing)  // List[Future[Int]]
    
    …然后,您可以将它们缩减为单个未来项目

    val fi = Future.reduce(lfi)(_+_)  // Future[Int]