我有一个整数列表{2,4,6,8,9,10,12}
为简化我的问题,我的目标是获取所有偶数整数,直到遇到奇数为止。所以我的结果应该是-> {2,4,6,8,9}
另外,我有一个演员说数字是偶数还是奇数(为简单起见)
我已经完成以下操作:-
CompletionStage<List<Integer>> result = Source.from(integerList)
.ask(oddEvenActor, OddEvenResponse.class, Timeout.apply(1, TimeUnit.SECONDS))
.map(oddEvenResult -> if(oddEvenResult.isOdd()){
//stop processing further elements
}
else {
return oddEvenResult.number();
})
.runWith(Sink.seq(), materializer)
那么一旦遇到奇数元素,我如何才能停止对其他元素的处理?
流完成后,CompletionStage“结果”应包含2、4、6、8、9。
我签出了statefulMapConcat(https://doc.akka.io/docs/akka/current/stream/operators/Source-or-Flow/statefulMapConcat.html) 但是,此操作仍将处理9之后的其他元素,因为该角色仍会被“询问”
我当然可以执行以下操作:-
具有一个resultList变量(全局),我执行一个resultList.add(oddEvenResult.number()),然后在遇到奇数时引发异常。我必须编写一个自定义的异常类来附带此全局resultList。
按照@Jeffrey Chung的建议使用takeWhile,但是OddEvenActoor仍然“请求”处理元素10和12。这毫无意义。
有没有更清洁的方法来实现这一目标?
答案 0 :(得分:3)
使用takeWhile
。在Scala中,这将类似于以下内容:
implicit val timeout: akka.util.Timeout = 3.seconds
val result: Future[Seq[Int]] =
Source(List(2, 4, 6, 8, 9, 10, 12))
.ask[OddEvenResponse](oddEvenActor)
.takeWhile(resp => !resp.isOdd, true)
.map(_.number)
.runWith(Sink.seq)
请注意在调用takeWhile
时使用inclusive
布尔标志,如果要保留第一个奇数,则必须这样做。
相当于Java的样子。
答案 1 :(得分:0)
如果您想保留演员,则可以实现它,例如,如下所示(在Scala中):
implicit val system = ActorSystem("StopOnOdd")
implicit val materializer = ActorMaterializer()
class StopOnOdd extends Actor with ActorLogging {
override def receive: Receive = {
case x: Int if x % 2 == 0 =>
log.info(s"Just received an even int: $x")
sender() ! x
case x: Int if x % 2 == 1 =>
log.info(s"Just received an odd number: $x Stop processing.")
context.become(dontProcess)
case _ =>
}
private def dontProcess: Receive = {
case x =>
log.info(s"Dropping $x because odd number was received.")
}
}
def main(args: Array[String]): Unit = {
val stopOnOdd = system.actorOf(Props[StopOnOdd], "simpleActor")
val source = Source(List(2,4,6,8,9,10,12))
implicit val timeout: Timeout = Timeout(2.seconds)
val stopOnOddFlow = Flow[Int].ask[Int](parallelism = 1)(stopOnOdd)
source.via(stopOnOddFlow).to(Sink.foreach[Int](number => println(s"Got number: $number"))).run()
}
输出为:
[INFO] [07/29/2020 16:37:14.618] [StopOnOdd-akka.actor.default-dispatcher-4]
[akka://StopOnOdd/user/simpleActor] Just received an even int: 2
Got number: 2
[INFO] [07/29/2020 16:37:14.625] [StopOnOdd-akka.actor.default-dispatcher-2]
[akka://StopOnOdd/user/simpleActor] Just received an even int: 4
Got number: 4
Got number: 6
[INFO] [07/29/2020 16:37:14.627] [StopOnOdd-akka.actor.default-dispatcher-4]
[akka://StopOnOdd/user/simpleActor] Just received an even int: 6
Got number: 8
[INFO] [07/29/2020 16:37:14.627] [StopOnOdd-akka.actor.default-dispatcher-4]
[akka://StopOnOdd/user/simpleActor] Just received an even int: 8
[INFO] [07/29/2020 16:37:14.628] [StopOnOdd-akka.actor.default-dispatcher-4]
[akka://StopOnOdd/user/simpleActor] Just received an odd number: 9 Stop processing.