【问题标题】:Scala Future with Option()带有 Option() 的 Scala 未来
【发布时间】:2014-12-02 08:50:02
【问题描述】:

我正在使用未来创建三个演员任务,然后在完成后尝试收集所有三个。 当前代码如下:

implicit val timeout = Timeout(5.seconds)
  val result1 = actor1 ? DataForActor(data)
  val result2 = actor2 ? DataForActor(data)
  val result3 = actor3 ? DataForActor(data)
  val answer = for {
    a <- result1.mapTo[List[ResultData]]
    b <- result2.mapTo[List[ResultData]]
    c <- result3.mapTo[List[ResultData]]
  } yield (a ++ b ++ c).sorted
  answer onComplete {
    case Success(resultData) =>
      log.debug("All actors completed succesffully")
      successActor ! SuccessData(resultData.take(2))
    case Failure(resultData) =>
      log.info("actors failed")
  }

每个参与者(actor1、actor2、actor3)操作数据并返回 None 或 Option(List(resultData)),如下代码所示:

val resultData = if(data.size == 0) None else {
  data.map {
    ...
    try {
      ... //manipulation on resultData
      Option(resultData)
    }
    catch {
      case e: Exception => None
    }
  }.flatten
}

for 语句连接来自每个参与者的列表,并生成一个长 List(resultData)。

我希望在一个参与者返回 None 的情况下,它的结果是 for 语句不会向连接添加任何内容,即 List()。

一个例子:

如果我得到: 结果 1 = 列表 (1, 2, 3), 结果 2 = 无, 结果3 = 列表(4, 5),

我想要: resultData = List(1, 2, 3, 4, 5)

【问题讨论】:

  • 在任何情况下都尝试返回相同的类型。您应该返回 Nil 而不是 None 或使用 Option[List[ResultData]]

标签: scala option future


【解决方案1】:

您可以在mapTo 之前将None 替换为Nil

result1.map{
  case None => Nil
  case x => x
}.mapTo[List[ResultData]]

请注意,您应该避免使用泛型类型的 mapTo,例如 List

Future("x" :: Nil).mapTo[List[Int]]
// res0: scala.concurrent.Future[List[Int]]

Future("x" :: Nil).mapTo[List[Int]] foreach { _.map( _ + 1 ) }
// java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer

由于类型擦除mapTo 无法证明您拥有Int 的列表,而不是其他类型的List。在actor的receive方法中使用case l: List[Int]会遇到同样的问题。

您应该像这样为您的消息创建特殊类:

sealed trait ResultList { def data: List[ResultData] }
case class NotEmptyResult(data: List[ResultData]) extends ResultList 
case object EmptyResult extends ResultList { def data: List[ResultData] = Nil }

result1.mapTo[ResultList]

【讨论】:

  • 感谢您的出色回答。至于您对带有 List 泛型的 mapTo 的评论,您会推荐什么来代替 mapTo?
  • @user3370773:你可以使用 mapTo 和非泛型类(见更新)。问题不在 mapTo 方法中 - 你会在 actor 中的 receive 方法中遇到同样的问题。
猜你喜欢
  • 1970-01-01
  • 2018-06-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-11-08
  • 2017-08-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多