Tal*_*ala 22 scala scala-collections
我已经在Scala中尝试了不同的集合来对它的元素进行求和,它们比Java和它的数组(for循环)慢得多.Scala有没有像Java数组一样快的方法?
我听说scala 2.8中的数组与java相同,但实际上它们要慢得多
Rex*_*err 29
在Scala中对数组进行索引在Scala中与在Java中一样快.(Scala的"for"循环不是Java的低级构造,因此不会按照你想要的方式工作.)
因此,如果在Java中你看到
for (int i=0 ; i < array.length ; i++) sum += array(i)
Run Code Online (Sandbox Code Playgroud)
在Scala你应该写
var i=0
while (i < array.length) {
sum += array(i)
i += 1
}
Run Code Online (Sandbox Code Playgroud)
如果你适当地做基准测试,你会发现速度没有区别.
如果你还有迭代器,那么Scala在大多数情况下都和Java一样快.例如,如果您有一个双打的ArrayList,并且在Java中使用它们添加它们
for (double d : arraylist) { sum += d }
Run Code Online (Sandbox Code Playgroud)
然后在Scala中,如果使用像ArrayBuffer这样的等效数据结构,你的速度大致相同
arraybuffer.foreach( sum += _ )
Run Code Online (Sandbox Code Playgroud)
与任何一个并没有太远的距离
sum = (0 /: arraybuffer)(_ + _)
sum = arraybuffer.sum // 2.8 only
Run Code Online (Sandbox Code Playgroud)
但请记住,混合高级和低级构造会受到惩罚.例如,如果您决定从数组开始,然后在其上使用"foreach"而不是索引,则Scala必须将其包装在一个集合中(ArrayOps在2.8中)以使其工作,并且通常必须将其包装基元也是如此.
无论如何,对于基准测试,这两个功能是你的朋友:
def time[F](f: => F) = {
val t0 = System.nanoTime
val ans = f
printf("Elapsed: %.3f\n",1e-9*(System.nanoTime-t0))
ans
}
def lots[F](n: Int, f: => F): F = if (n <= 1) f else { f; lots(n-1,f) }
Run Code Online (Sandbox Code Playgroud)
例如:
val a = Array.tabulate(1000000)(_.toDouble)
val ab = new collection.mutable.ArrayBuffer[Double] ++ a
def adSum(ad: Array[Double]) = {
var sum = 0.0
var i = 0
while (i<ad.length) { sum += ad(i); i += 1 }
sum
}
// Mixed array + high-level; convenient, not so fast
scala> lots(3, time( lots(100,(0.0 /: a)(_ + _)) ) )
Elapsed: 2.434
Elapsed: 2.085
Elapsed: 2.081
res4: Double = 4.999995E11
// High-level container and operations, somewhat better
scala> lots(3, time( lots(100,(0.0 /: ab)(_ + _)) ) )
Elapsed: 1.694
Elapsed: 1.679
Elapsed: 1.635
res5: Double = 4.999995E11
// High-level collection with simpler operation
scala> lots(3, time( lots(100,{var s=0.0;ab.foreach(s += _);s}) ) )
Elapsed: 1.171
Elapsed: 1.166
Elapsed: 1.162
res7: Double = 4.999995E11
// All low level operations with primitives, no boxing, fast!
scala> lots(3, time( lots(100,adSum(a)) ) )
Elapsed: 0.185
Elapsed: 0.183
Elapsed: 0.186
res6: Double = 4.999995E11
Run Code Online (Sandbox Code Playgroud)
BAR*_*BAR 11
你现在可以简单地使用sum.
val values = Array.fill[Double](numValues)(0)
val sumOfValues = values.sum
Run Code Online (Sandbox Code Playgroud)
小智 7
正确的 Scala 或函数式是这样做的:
val numbers = Array(1, 2, 3, 4, 5)
val sum = numbers.reduceLeft[Int](_+_)
Run Code Online (Sandbox Code Playgroud)
查看此链接以获取语法的完整解释:http : //www.codecommit.com/blog/scala/quick-explanation-of-scalas-syntax
我怀疑这会比其他答案中描述的方式更快,但我还没有测试过,所以我不确定。在我看来,这是正确的方法,因为 Scala 是一种函数式语言。