scala - 为什么 Source.fromIterator 需要 Function0[Iterator[T]] 作为参数而不是 Iterator[T]?

标签 scala akka-stream

基于:source code

我不明白为什么 Source.fromIterator 的参数是 Function0[Iterator[T]]而不是 Iterator[T] .

这有实际的原因吗?我们能不能把签名改成def fromIterator(iterator: => Iterator[T])反而 ? (避免做 Source.fromIterator( () => myIterator) )

最佳答案

根据 the docs :

The iterator will be created anew for each materialization, which is the reason the method takes a function rather than an iterator directly.



流阶段应该是可重用的,因此您可以将它们实现不止一个。但是,给定的迭代器(通常)只能使用一次。如 fromIterator创建了一个引用现有迭代器(无论是通过名称还是引用传递)的 Source 再次尝试实现它可能会失败,因为底层迭代器将被耗尽。

为了解决这个问题,源需要能够实例化一个新的迭代器,所以 fromIterator允许您提供必要的逻辑来执行此操作作为供应商功能。

这是我们不希望发生的事情的示例:
implicit val system = akka.actor.ActorSystem.create("test")
implicit val mat = akka.stream.ActorMaterializer(system)

val iter = Iterator.range(0, 2)
// pretend we pass the iterator directly...
val src = Source.fromIterator(() => iter)

Await.result(src.runForEach(println), 2.seconds)
// 0
// 1
// res0: akka.Done = Done

Await.result(src.runForEach(println), 2.seconds)
// res1: akka.Done = Done
// No results???

这很糟糕,因为来源 src不可重复使用,因为它不会在后续运行中提供相同的输出。但是,如果我们懒惰地创建迭代器,它会起作用:
val iterFunc = () => Iterator.range(0, 2)
val src = Source.fromIterator(iterFunc)

Await.result(src.runForEach(println), 2.seconds)
// 0
// 1
// res0: akka.Done = Done

Await.result(src.runForEach(println), 2.seconds)
// 0
// 1
// res1: akka.Done = Done

关于scala - 为什么 Source.fromIterator 需要 Function0[Iterator[T]] 作为参数而不是 Iterator[T]?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40683078/

相关文章:

scala - 理解 Scala 中的 "type arguments do not conform to type parameter bounds"错误

list - 如何使用scala基于一个列表元素进行分组来创建列表列表?

mysql - FlywayDB : Migration fails with "Error executing statement", 但手动运行迁移 SQL 代码有效

java - 如何在 Play 测试中从基于 InputStream 的结果中获取内容

scala - 在Akka流中,如何从 future 集合中创建无序来源

scala - Int上的匹配表达式并不详尽

Int 和 Long 的 Scala 中值函数

scala - 测试 Akka react 流

java - 如何正确构建 Akka Graph

streaming - 具有默认调度程序的响应式(Reactive)卡夫卡?