2016-03-23 2 views
1

Что это лучший способ, чтобы перейти отScala, выполнить карту фьючерсов

Map[String, Future[A]] 

в

Map[String, A] 

где А является результатом выполнения Соответствующее будущегокиевстар?

Это не будет компилироваться:

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

как я не могу смешивать фьючерсы и итерируемых в то же самое для понимания.

+2

Вы понимаете, что для перехода от 'Map [String, Future [A]]' to 'Map [String, A]' вам не останется выбора, кроме как заблокировать? Это нормально в вашем случае? В противном случае, я думаю, что вы действительно хотите перейти от «Map [String, Future [A]]» к «Будущее [Карта [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

Смежные вопросы