Scala Future with Option()

piwo6bdm  于 2022-11-09  发布在  Scala
关注(0)|答案(1)|浏览(189)

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

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")
  }

每个参与者(acter1、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语句连接来自每个参与者的列表,并生成一个长列表(ResultData)。
我希望在一个参与者返回NONE的情况下,它在for语句中的结果不会向连接中添加任何东西,即list()。
举个例子:
如果我得到:结果1=列表(1,2,3),结果2=无,结果3=列表(4,5),
我想要:ResultData=List(1,2,3,4,5)

cgvd09ve

cgvd09ve1#

您可以在mapTo之前将None替换为Nil,方法如下:

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

请注意,应避免使用List这样的泛型类型的mapTo

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。在执行元的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]

相关问题