如何将HashMap [T,Future [N]]转换为Future [HashMap [T,N]]

时间:2017-02-21 13:04:58

标签: scala future

我知道存在

Future.sequence

List[Future[T]]转换为Future[List[T]]

有没有办法将HashMap[T,Future[N]]转换为Future[HashMap[T,N]]

2 个答案:

答案 0 :(得分:4)

不确定开箱即用的功能,但我自己也是这样做的:

import scala.collection.mutable.HashMap
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global

val a: HashMap[Int, Future[Int]] = HashMap((1, Future(42)), (2, Future(43)))
val iterOfFutures = a.map { case (k, v) => v.map(vv => (k, vv)) }
val futureMap: Future[Map[Int, Int]] = Future.sequence(iterOfFutures).map(_.toMap)

futureMap.map(println) // Map(2 -> 43, 1 -> 42)
Thread.sleep(100)

修改

不是问题的要点,但如果你想要一个可变的HashMap而不是不可变的Map那么你必须转换它。这是一个不可思议的方式,也许还有更好的东西:

val futureMap: Future[HashMap[Int, Int]] = 
  Future.sequence(iterOfFutures).map(s => HashMap(s.toSeq: _*))

答案 1 :(得分:2)

标准库中没有内置任何内容,但实现起来很容易,例如

def combineFutures[K,V](m: Map[K,Future[V]]): Future[Map[K,V]] = {
    m.foldLeft(Future.successful(Map.empty[K, V])) {
        case (futureAcc: Future[Map[K, V]], (k: K, futureV: Future[V])) =>
            for {
                acc <- futureAcc
                v <- futureV
            } yield acc + (k -> v)
    }
}

// Mutable HashMap version
import scala.collection.mutable.HashMap
def combineFutures[K,V](m: HashMap[K,Future[V]]): Future[HashMap[K,V]] = {
    m.foldLeft(Future.successful(HashMap.empty[K, V])) {
        case (futureAcc: Future[HashMap[K, V]], (k: K, futureV: Future[V])) =>
            for {
                acc <- futureAcc
                v <- futureV
            } yield {
                acc.put(k, v)
                acc
            }
    }
}

(为了清楚起见,我在上面添加了一些额外的不必要的类型注释。)