Scala - 将Map中的值映射到另一个Map

时间:2016-04-06 20:30:35

标签: scala scala-collections

我需要将我的RDD中的字段映射到另一个地图中的另一个字段UserDAO.users我试图找出这里的映射但是还不能返回username。当我进行foreach打印scala.concurrent.impl.Promise$DefaultPromise@7c4c5ddd

时,我会在更新的地图中看到这个

这是我的代码段:

 rdd.map { l => {
      l.map { case (k, v) => {
        k match {
          case "a_userid" => {
            l.updated("a_username", userDAO.users.map(c => c.filter(f => f.userid == v.toInt)).map(y => y.map(e => e.username)))
          }
          case _ =>
            }
          }
        }
      }
    }

基本上,

rdd - RDD[Map[String, String]]

UserDAO.users - Future[Seq[User]] - 其中User是案例类

并返回更新后的rdd - RDD[Map[String, String]]

-

知道如何解决这个问题吗?

由于

1 个答案:

答案 0 :(得分:1)

我已重写您的代码以使其正常工作。请注意,它涉及阻止,否则没有其他方法可以获得具体的RDD[Map[String, String]]

为了清楚起见,我省略了rdd.map部分。

第一个变种。我使用了您在map内阅读用户的方法。请注意,这是非常低效的,因为每次迭代都会读取所有用户,即1100万次:

// rdd.map ommitted
l.get("a_userid").flatMap {
  userId:String =>
    val newUserName:Option[String] =
      Await.result(userDAO.users
        .map(c => c.find(f => f.userid == userId.toInt))
        .map(y => y.map(e => e.username)),
        30 seconds
      )
    newUserName.map(l.updated("a_username", _))
}.getOrElse(l)

替代方法涉及事先将用户读取到地图。那张地图随后将播放给所有火花工人。由于你的地图不是很大,所以很好。这种方法效率更高,因为您在RDD上每次迭代只执行一次地图查找,这很快。

val users:Map[Int, String] =  Await.result(userDAO.users
  .map(uss => uss.map(u => u.userid -> u.username).toMap),
  30 seconds
)

// rdd.map ommitted
l.get("a_userid").flatMap {
  userId:String =>
    users.get(userId.toInt).map(l.updated("a_username", _))
}.getOrElse(l)

UPD :仅仅为了完整起见,这是另一个异步变体:

userDAO.users
  .map(uss => uss.map(u => u.userid -> u.username).toMap)
  .map { users:Map[Int, String] =>
      rdd.map { l:Map[String, String] =>
        l.get("a_userid").flatMap {
          userId:String =>
            users.get(userId.toInt).map(l.updated("a_username", _))
        }.getOrElse(l)
      }
  }

它遵循与variant2相同的方法,但返回Future[RDD[Map[String, String]]]而不是具体结果。