首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在Scala中对集合求和的最快方法是什么

在Scala中对集合求和的最快方法是什么
EN

Stack Overflow用户
提问于 2010-06-23 23:05:17
回答 4查看 41.6K关注 0票数 24

我在Scala中尝试过不同的集合来计算元素的和,它们比数组的Java sum慢得多(使用for周期)。有没有办法让Scala像Java数组一样快?

我听说在Scala2.8中数组和java中的数组是一样的,但是在实践中它们要慢得多

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2010-06-24 01:01:01

在Scala中,在while循环中索引数组的速度与在Java中一样快。(Scala的"for“循环不是Java的低级结构,因此不会以您想要的方式工作。)

因此,如果您在Java中看到

代码语言:javascript
复制
for (int i=0 ; i < array.length ; i++) sum += array(i)

在Scala中,您应该编写

代码语言:javascript
复制
var i=0
while (i < array.length) {
  sum += array(i)
  i += 1
}

如果您适当地执行基准测试,您将不会发现速度上的差异。

如果你有迭代器,那么Scala在大多数方面都和Java一样快。例如,如果您有一个双精度的ArrayList,并且在Java语言中使用以下命令添加它们

代码语言:javascript
复制
for (double d : arraylist) { sum += d }

那么在Scala中,如果使用像ArrayBuffer这样的等效数据结构,速度将大致与

代码语言:javascript
复制
arraybuffer.foreach( sum += _ )

而且也不会偏离目标太远

代码语言:javascript
复制
sum = (0 /: arraybuffer)(_ + _)
sum = arraybuffer.sum  // 2.8 only

不过,请记住,混合高级和低级构造是有代价的。例如,如果您决定从一个数组开始,然后对它使用"foreach“而不是索引它,Scala必须将它包装在一个集合中(2.8中的ArrayOps)才能使它工作,而且通常还必须对原语进行装箱。

无论如何,对于基准测试,这两个函数是您的朋友:

代码语言:javascript
复制
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) }

例如:

代码语言:javascript
复制
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
票数 30
EN

Stack Overflow用户

发布于 2015-02-04 10:09:20

您现在可以简单地使用sum。

代码语言:javascript
复制
val values = Array.fill[Double](numValues)(0)

val sumOfValues = values.sum
票数 17
EN

Stack Overflow用户

发布于 2015-01-29 18:45:57

正确的scala或函数是这样做的:

代码语言:javascript
复制
val numbers = Array(1, 2, 3, 4, 5)
val sum = numbers.reduceLeft[Int](_+_)

有关语法的完整解释,请查看此链接:http://www.codecommit.com/blog/scala/quick-explanation-of-scalas-syntax

我怀疑这是否会比其他答案中描述的方法更快,但我没有测试过,所以我不确定。在我看来,这是正确的方式,因为Scala是一种函数式语言。

票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3102872

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档