【发布时间】:2014-05-16 05:30:46
【问题描述】:
要迭代一个迭代器,我们可以调用它的foreach 或使用while 循环。 foreach的实现是:
def foreach[U](f: A => U) { while (hasNext) f(next()) }
所以我认为foreach应该和while(iterator.hasNext)一样快,但是在做了一些测试后,结果让我很惊讶。
我的测试代码:
def getSize2[T](i: Iterator[T]) = {
var count = 0
val f = (a: T) => count += 1
while(i.hasNext) {
f(i.next)
}
count
}
def getSize3[T](i: Iterator[T]) = {
var count = 0
val f = (a: T) => count += 1
i.foreach(f)
count
}
很奇怪getSize2比getSize3快3倍!
有人知道那里发生了什么吗?
编辑: 粘贴我的测试程序
def main(args: Array[String]) {
val data = 0 to 100000000
val start2 = System.nanoTime
(0 to 100).foreach(_ => getSize2(data.iterator))
println("get size, while loop, using function: " + (System.nanoTime - start2)/1000000)
val start3 = System.nanoTime
(0 to 100).foreach(_ => getSize3(data.iterator))
println("get size, foreach: " + (System.nanoTime - start3)/1000000)
}
我的操作系统:ubuntu 12.04,scala 版本:2.10.3
【问题讨论】:
-
你能写出你是如何测量执行速度的吗?我的意思是您执行的实际代码和命令行。另外 scala 版本和您正在运行的操作系统。
-
查看字节码,您会发现 foreach 正在执行更多调用。
-
这很有趣,因为我看到了相反的结果。 while (iter.hasNext) { count += 1; iter.next() } 需要大约 6 倍的时间。
-
更新:使用 Scala 2.11.12 检查此结果,我发现给定的测试代码使用具有一百万个整数的底层 mutable.ArrayBuffer 以大约 30% 的速度运行 while 循环。但是,如果将“Iterable[T]”参数更改为“Iterable[T]”(将“val i = input.iterator”添加到 while 循环中),则 while 循环的运行速度大致相同,但“foreach”在这里跑得快十倍以上。