我已编写此代码并且可以正常使用
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(_ + _)
答案 0 :(得分:9)
Future.sequence
将Traversable[Future[T]]
转换为Future[Traversable[T]]
(如果原始列表中的任何期货失败,则此未来将失败)。之后,您只需拨打sum
关于此未来的内容:
Future.sequence(x).map(_.sum)
答案 1 :(得分:2)
TL; DR 使用:Future.reduce(futures)(_ + _)
您的代码示例的主要问题是Traversable#reduce
和Future#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)})