在Scala中与Regexes合作后我使用了Iterators
,但我并不理解它的兴趣。
我知道它有一个状态,如果我在它上面调用next()方法,它每次都会输出不同的结果,但是我没有看到任何我可以用它做的事情,这是不可能的{{1 }}
它似乎不像Akka Streams那样工作(例如),因为下面的例子直接打印所有数字(没有等待我想象的一秒):
Iterable
那么使用lazy val a = Iterator({Thread.sleep(1000); 1}, {Thread.sleep(1000); 2}, {Thread.sleep(1000); 3})
while(a.hasNext){ println(a.next()) }
的目的是什么?
答案 0 :(得分:5)
也许,迭代器最有用的属性是它们很懒惰。 考虑这样的事情:
(1 to 10000)
.map { x => x * x }
.map { _.toString }
.find { _ == "4" }
此代码段将10000个数字平方,然后生成10000个字符串,然后返回第二个字符串。 另一方面,这是:
(1 to 10000)
.iterator
.map { x => x * x }
.map { _.toString }
.find { _ == "4" }
...只计算两个方块,并生成两个字符串。
当你需要包装一些设计不佳的(java?)对象以便能够以函数式处理它们时,迭代器也常常很有用:
val rs: ResultSet = jdbcQuery.executeQuery()
new Iterator {
def next = rs
def hasNext = rs.next
}.map { rs =>
fetchData(rs)
}
Streams类似于迭代器 - 它们也很懒惰,也可用于包装:
Stream.continually(rs).takeWhile { _.next }.map(fetchData)
但主要区别在于流记住了实现的数据,因此您可以多次遍历它们。这很方便,但如果原始数据量非常大,可能会很昂贵,特别是如果它被过滤到更小的尺寸:
Source
.fromFile("huge_file.txt")
.getLines
.filter(_ == "")
.toList
这仅大致(忽略缓冲,对象开销和其他特定于实现的细节),内存量,将一行保留在内存中,加上文件中有许多空行。
另一方面:
val reader = new FileReader("huge_file.txt")
Stream
.continually(reader.readLine)
.takeWhile(_ != null)
.filter(_ == "")
.toList
...将以内存中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.
答案 1 :(得分:1)
对迭代器http://www.scala-lang.org/docu/files/collections-api/collections_43.html
有一个很好的解释迭代器不是一个集合,而是一种访问它的方法 集合的元素一个接一个。关于的两个基本操作 迭代器是下一个和hasNext。对it.next()的调用将返回 迭代器的下一个元素并提升迭代器的状态。 然后在同一个迭代器上再次调用将生成元素 一个超出之前返回的一个。如果没有更多的元素 要返回,对next的调用将抛出NoSuchElementException。
答案 2 :(得分:1)
首先,您应该了解您的示例有什么问题:
lazy val a = Iterator({Thread.sleep(1); 1},{Thread.sleep(1); 2}, {了Thread.sleep(2); 3})while(a.hasNext){println(a.next())}
如果查看Iterator
的应用方法,您会看到没有按姓名调用,因此Thread.sleep
方法同时调用apply
Thread.sleep
调用。此外,sleep
以毫秒为单位获取睡眠时间参数,因此如果您想在一秒内Thread.sleep(1000)
线程,则应通过val a = Iterator.iterate(1)(x => {Thread.sleep(1000); x+1})
。
伴随对象具有允许您执行下一步的其他方法:
Iterator
当您需要处理大数据时, val it = new Iterator[Int] {
var i = -1
def hasNext = true
def next(): Int = { i += 1; i }
}
非常有用。您也可以实现自己的:
{{1}}
答案 3 :(得分:0)
我没有看到任何我可以用它做的事情,这是不可能的Iterable
事实上,大多数收藏品也可以用Array完成,但我们不这样做,因为它不太方便
同样的理由适用于迭代器,如果你想建模一个可变状态,那么迭代器更有意义。
例如,Random的实现方式类似于迭代器,因为它的用例更适合迭代器,而不是迭代。