2016-03-23 284 views
1

的地圖是什麼,從斯卡拉,執行期貨

Map[String, Future[A]] 

Map[String, A] 

其中A是對應未來的執行結果的最佳方式?

這不會編譯:

val results = for { 
    (key, future) <- myMap 
    result <- future 
} yield (key, result) 

,因爲我可以在相同的理解不能混用期貨和iterables。

+2

你意識到從Map [String,Future [A]]到'Map [String,A]'你將別無選擇,只能阻止?你的情況好嗎?否則,我認爲你真正想要的是從Map [String,Future [A]]'到'Future [Map [String,A]]' –

+0

@RégisJean-Gilles好評。這[回答](http://stackoverflow.com/questions/17479160/how-to-convert-mapa-futureb-to-futuremapa-b)包含提示也要這樣做。 – ticofab

回答

2

如果你把它轉換成Seq[Future[(String,A)]],您就可以使用Future.fold把它找回來一個Future[Map[...]]

def transform[A](m: Map[String, Future[A]]): Future[Map[String, A]] = { 
    val seq: Seq[Future[(String, A)]] = m.toSeq.map { case (key, f) => 
    f.map(i => key -> i) 
    } 

    Future.fold(seq)(Map.empty[String, A])(_ + _) 
} 

然後贖單的未來爲正常。

0

像這樣的東西可能:

map.mapValues { Await.result(_, 5 seconds) } 
+0

你的第二個選擇不會編譯。 –

+0

確實。刪除它。 – Dima

-1

迪馬已經給使用Await答案。但是,如果未來失敗,它會引發異常。

您可以將其中的類型進一步包裝爲Try,然後執行.collect以僅過濾成功期貨(請查看官方API)。

import scala.util.{ Try, Success } 

val results = myMap 
    .map { 
     case (key, value) => key => Try(Await.result(value, 5.seconds)) 
    } 
    .collect { 
     case (key, Success(value)) => key -> value 
    } 

通過上面的調用,您可以自動放棄失敗的期貨並僅收集成功的期貨。

+0

這將不起作用:地圖中的值是「Future」類型,與「Success」不兼容。事情是,你必須阻止並等待某個地方,從「未來」到現實(「現在」)的結果。 – Dima

+0

阿哈的確如此。我想這次我將它與'Try'混合。我編輯了我的答案。 'collect'只有在您檢索到某個地方的結果並將其轉換爲實際的'Try'後才能使用。 – bow