Scala how to summarize the list of futures

I wrote this code and it works

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

So when I run this, I get 120. Good.

but I don't like the fact that I am summing the values ​​in a for loop

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

What if I call my functions like

val x = List(TestFuture2.bigCalc, TestFuture2.bigCalc, TestFuture2.bigCalc, TestFuture2.bigCalc, TestFuture2.bigCalc)

Now, how will I summarize?

I tried

x.reduce(_ + _)

but that will not work.

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

Future.sequenceconverts a Traversable[Future[T]]to Future[Traversable[T]](this future will be unsuccessful if any of the futures in the source list did not work). After that, you can simply call the sumcontents of this future:

Future.sequence(x).map(_.sum)
+9
source

TL DR Usage: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

If you want to use abbreviation, you can do it as follows.

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

All Articles