根据未来的运营情况保留一笔款项

时间:2016-07-08 21:43:36

标签: scala

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

我正在尝试仅使用不可变数据。

这样的事情:

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

2 个答案:

答案 0 :(得分:2)

尝试使用类似的东西:

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))
  }
}

这里发生了什么:

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

    如果您的源集合非常大,可能会出现这种方法的唯一问题,因此它不适合您的堆,并且您希望在足够的Intures of Int准备就绪时应用操作(假设操作顺序不重要) )。如果你愿意,答案应该有点复杂。

答案 1 :(得分:1)

如果您从一系列项目开始......

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]