Scala:使用迭代器有什么兴趣?

Sim*_*mon 1 iterator scala

我曾经使用IteratorsScala中的Regexes,但我并不理解它的兴趣.
我知道它有一个状态,如果我在它上面调用next()方法,它每次都会输出不同的结果,但是我没有看到任何可以用它做的事情,而这是不可能的Iterable.

并且它似乎不像Akka Streams(例如)那样工作,因为以下示例直接打印所有数字(没有等待我想象的一秒):

lazy val a = Iterator({Thread.sleep(1000); 1}, {Thread.sleep(1000); 2}, {Thread.sleep(1000); 3}) 
while(a.hasNext){ println(a.next()) } 
Run Code Online (Sandbox Code Playgroud)

那么使用的目的是Iterators什么?

Dim*_*ima 5

也许,迭代器最有用的特性是它们很懒惰.考虑这样的事情:

   (1 to 10000)
     .map { x => x * x }
     .map { _.toString }
     .find { _ == "4" }
Run Code Online (Sandbox Code Playgroud)

此片段将平方10000个数字,然后生成10000个字符串,然后返回第二个.这另一方面:

   (1 to 10000)
     .iterator
     .map { x => x * x }
     .map { _.toString }
     .find { _ == "4" }
Run Code Online (Sandbox Code Playgroud)

...只计算两个正方形,并生成两个字符串.

当您需要包装一些设计不佳的(java?)对象以便能够以函数样式处理它们时,迭代器通常也很有用:

val rs: ResultSet = jdbcQuery.executeQuery()
new Iterator { 
   def next = rs
   def hasNext = rs.next
}.map { rs =>
   fetchData(rs)
}
Run Code Online (Sandbox Code Playgroud)

流类似于迭代器 - 它们也是惰性的,也可用于包装:

Stream.continually(rs).takeWhile { _.next }.map(fetchData)
Run Code Online (Sandbox Code Playgroud)

但主要区别在于流记住了实现的数据,因此您可以多次遍历它们.这很方便,但如果原始数据量非常大,可能会很昂贵,特别是如果它被过滤到更小的尺寸:

Source
  .fromFile("huge_file.txt")
  .getLines 
  .filter(_ == "")
  .toList
Run Code Online (Sandbox Code Playgroud)

这仅大致(忽略缓冲,对象开销和其他特定于实现的细节),内存量,将一行保留在内存中,加上文件中有许多空行.

这另一方面:

val reader = new FileReader("huge_file.txt")
Stream
  .continually(reader.readLine)
  .takeWhile(_ != null)
  .filter(_ == "")
  .toList
Run Code Online (Sandbox Code Playgroud)

...将最终得到内存中的全部内容huge_file.txt.

最后,如果我正确理解了您的示例的意图,那么您可以使用迭代器来完成它:

val iterator = Seq(1,2,3).iterator.map { n => Thread.sleep(1000); n }
iterator.foreach(println)
// Or while(iterator.hasNext) { println(iterator.next) } as you had it.
Run Code Online (Sandbox Code Playgroud)