私は Scala Akka ライブラリを使用していて、ちょっとした問題に遭遇しました。タイトルが示すように、私はに変換する必要がありMap[A, Future[B]]ますFuture[Map[A,B]]。Future.sequenceリストのようなイテラブルに使用できることは知っていますが、この場合は機能しません。
私は疑問に思っていました.Scalaでこの変換を行うためのきれいな方法はありますか?
これがうまくいくかどうかを確認してください:
val map = Map("a" -> future{1}, "b" -> future{2}, "c" -> future{3})    
val fut = Future.sequence(map.map(entry => entry._2.map(i => (entry._1, i)))).map(_.toMap)
アイデアは、マップのキーのIterablefor にマップをマップしTuple、そのキーに関連付けられた未来の結果をマップすることです。そこからそれができsequence、Iterable集約を取得したら、それをマップし、それを経由でマップにFuture変換します。  IterableTuplestoMap
さて、このアプローチに代わる方法は、sequence関数が行っていることと似たようなことを試してみることです。sequenceMap次のような関数を書くことができます:
def sequenceMap[A, B](in: Map[B, Future[A]])(implicit executor: ExecutionContext): Future[Map[B, A]] = {
  val mb = new MapBuilder[B,A, Map[B,A]](Map())
  in.foldLeft(Promise.successful(mb).future) {
    (fr, fa) => for (r <- fr; a <- fa._2.asInstanceOf[Future[A]]) yield (r += ((fa._1, a)))
  } map (_.result)
}
そして、次のような例で使用します。
val map = Map("a" -> future{1}, "b" -> future{2}, "c" -> future{3})    
val fut = sequenceMap(map)
fut onComplete{
  case Success(m) => println(m)
  case Failure(ex) => ex.printStackTrace()
}
これは、作成される中間コレクションが少なくなり、ExecutionContext.
コア Scala 2.12.x でできる最も簡潔なことは、
val futureMap = Map("a" -> future{1}, "b" -> future{2}, "c" -> future{3}) 
Future.traverse(futureMap.toList) { case (k, fv) => fv.map(k -> _) } map(_.toMap)
これは、(マップの値の) シーケンス結果を使用して、マップから値の取得を開始できるという promise を起動するというアイデアでも機能します。  mapValuesはマップの非厳密なビューを提供するためvalue.get.get、値を取得するときにのみ適用されます。そうです、あなたはあなたの地図を保つことができます!そのリンクの謎解きの無料広告。
import concurrent._
import concurrent.duration._
import scala.util._
import ExecutionContext.Implicits.global
object Test extends App {
  def calc(i: Int) = { Thread sleep i * 1000L ; i }
  val m = Map("a" -> future{calc(1)}, "b" -> future{calc(2)}, "c" -> future{calc(3)})
  val m2 = m mapValues (_.value.get.get)
  val k = Future sequence m.values
  val p = Promise[Map[String,Int]]
  k onFailure { case t: Throwable => p failure t }
  k onSuccess { case _ => p success m2 }
  val res = Await.result(p.future, Duration.Inf) 
  Console println res
}
これは、すべての値を出力して m2 マップを強制する REPL です。
scala> val m2 = m mapValues (_.value.get.get)
m2: scala.collection.immutable.Map[String,Int] = Map(a -> 1, b -> 2, c -> 3)
これは、まだ未来にある先物と同じことを示しています。
scala>   val m2 = m mapValues (_.value.get.get)
java.util.NoSuchElementException: None.get
マップ値のすべての先物を待つ新しい未来を作成し、マップを構築して返すだけです。