我想解决以下问题:
我有一个未来[地图[A,B]].对于所有B,我需要应用一个将B转换为Future [C]的方法,并且我想要回馈Future [Map [A,C]]
这是我到目前为止的代码:
def getClients(clientIds: Seq[Int]): Future[Map[Int, ClientData]] = { def getClientData(clientInfo: ClientInfo): Future[ClientData] = clientInfo match { case ValidInfo(info) => getData(info) case _ => throw new Exception } client.getClients(clientIds) map { _.toMap map { case (clientId: Int, clientInfo: ClientInfo) => getClientData(clientInfo) map { clientData => (clientId, clientData) } } } }
此代码错误,因为它返回Iterable [Future [(Int,ClientData)]]
对于info getClients是一个thrift方法,它返回Map [Map [A,B]],其中Map是可变的,所以我需要首先使用toMap将它转换为不可变的映射.
预先感谢您的帮助!
scala> def f: Future[Map[String, Future[Int]]] = ??? f: Future[Map[String,Future[Int]]] scala> def x = for { | m <- f | i = m.map{ case (k, fv) => fv.map{ k -> _ } } | l <- Future.sequence(i) | } yield l.toMap x: Future[Map[String,Int]]
一步步:
转换Future[Map[A, Future[B]]]
为Future[Iterable[Future[(A, B)]]]
:
scala> def x1 = f.map{ _.map{ case (k, fv) => fv.map{ k -> _ } } } x1: Future[Iterable[Future[(String, Int)]]]
转换Iterable[Future[(A, B)]]
为Future[Iterable[(A, B)]]
和flatten
Future[Future[...]]
使用flatMap
:
scala> def x2 = x1.flatMap{ Future.sequence(_) } x2: Future[immutable.Iterable[(String, Int)]]
转换Iterable[(A, B)]
为Map[A, B]
:
scala> def x = x2.map{ _.toMap } x: Future[Map[String,Int]]
对于com.twitter.util.Future
你应该使用collect
的,而不是sequence
和toSeq
之前collect
因为它接受Seq
:
def x = for { m <- f i = m.map{ case (k, fv) => fv.map{ k -> _ } } l <- Future.collect(i.toSeq) } yield l.toMap