如何遍历Set [Future [Option [User]]]并改变地图

时间:2017-09-13 23:50:35

标签: scala

我有一个包含用户的可变地图:

val userMap = mutable.Map.empty[Int, User] // Int is user.Id

现在我需要加载新用户,并将它们添加到地图中。我有以下api方法:

def getNewUsers(): Seq[Int]
def getUser(userId: Int): Future[Option[User]]

所以我首先得到了我需要加载的所有用户:

val newUserIds: Set[Int] = api.getNewUsers

我现在需要加载每个用户,但不知道如何做getUser返回Future [Option [User]]。

我试过了:

api.getNewUsers().map( getUser(_) )

但是返回Set[Future[Option[User]]]

我不确定如何使用Set[Future[Option[User]]]立即更新我的userMap。

2 个答案:

答案 0 :(得分:2)

你必须等待所有的期货完成。您可以使用Future.sequenceSet[Future[_]]转换为Future[Set],这样您就可以等待它们全部完成:

val s: Set[scala.concurrent.Future[Some[User]]] = Set(Future(Some(User(1))), Future(Some(User(2))))

val f: Future[Set[Some[User]]] = Future.sequence(s)

f.map(users => users.foreach(u => /* your code here */))

然而,使用可变地图可能很危险,因为它可以让自己打开竞争条件。期货在不同的线程中执行,如果你在不同的线程中改变一个可变对象的状态,就会发生不好的事情。

答案 1 :(得分:0)

您可以使用Future.sequence:

  

将TraversableOnce [Future [A]]转换为   未来[TraversableOnce [A]]。用于将许多期货减少为一个   单一的未来   来自Scala Future

您可以尝试:

val result : Future[Seq[Option[User]]] = 
  Future.sequence(
      api.getNewUsers().map( getUser )
  )
result.andThen {
    case Success(users) => 
        users.flatten.foreach(u => yourMap += u.id -> u)
}