【问题标题】:How to traverse a Set[Future[Option[User]]] and mutate a map如何遍历 Set[Future[Option[User]]] 并改变地图
【发布时间】:2017-09-13 23:50:34
【问题描述】:

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

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。

【问题讨论】:

    标签: scala


    【解决方案1】:

    您必须等待所有 Futures 完成。您可以使用Future.sequence 将您的Set[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 */))
    

    但是,使用可变 Map 可能会很危险,因为它可能会让自己面临竞争条件。 Futures 在不同的线程中执行,如果你在不同的线程中改变可变对象的状态,就会发生不好的事情。

    【讨论】:

    • 可变映射在 akka 内部。
    【解决方案2】:

    你可以使用 Future.sequence:

    将 TraversableOnce[Future[A]] 转换为 未来[TraversableOnce[A]]。用于将许多 Future 简化为 单未来 来自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)
    }
    

    【讨论】:

      猜你喜欢
      • 2021-12-13
      • 1970-01-01
      • 2016-08-01
      • 1970-01-01
      • 2018-07-05
      • 1970-01-01
      • 2011-05-03
      • 2015-11-03
      • 1970-01-01
      相关资源
      最近更新 更多