Performance 填充一个列表是Scala的一个永久性随机双精度运算

Performance 填充一个列表是Scala的一个永久性随机双精度运算,performance,list,scala,Performance,List,Scala,我是Scala新手,正在尝试获取随机双精度值列表: 问题是,当我尝试运行它时,它比它的Java对应程序花费的时间太长了。有没有关于这是为什么的想法,或者关于更有效的方法的建议 def random: Double = java.lang.Math.random() var f = List(0.0) for (i <- 1 to 200000) ( f = f ::: List(random*100)) f = f.tail def random:Double=java.lang.

我是Scala新手,正在尝试获取随机双精度值列表:

问题是,当我尝试运行它时,它比它的Java对应程序花费的时间太长了。有没有关于这是为什么的想法,或者关于更有效的方法的建议

def random: Double = java.lang.Math.random()
var f = List(0.0)
for (i <- 1 to 200000)
 ( f = f ::: List(random*100)) 
 f = f.tail
def random:Double=java.lang.Math.random() var f=列表(0.0)
对于(i,您可以构造无限个随机双精度流:

def randomList(): Stream[Double] = Stream.cons(math.random, randomList)

val f = randomList().take(200000)

这将利用延迟求值,因此在实际需要之前,您不会计算值。尽管如此,即使求值全部200000也会很快。作为额外的好处,
f
不再需要是一个
var

,如果您使用可变状态,您应该使用一个可变集合,如缓冲区,您也可以使用
+=
(这将是java代码的真正对应项)

但是你为什么不使用列表理解呢

val f = for (_ <- 1 to 200000) yield (math.random * 100)

val f=for(p>另一种可能性是:

val it = Iterator.continually(math.random)
it.take(200000).toList

Stream
也有一个
连续
方法,如果您愿意的话。

您也可以这样实现:

List.fill(200000)(math.random)
这同样适用于例如数组

Array.fill(200000)(math.random)

等等…

还有更多选项!尾部递归:

def randlist(n: Int, part: List[Double] = Nil): List[Double] = {
  if (n<=0) part
  else randlist(n-1, 100*random :: part)
}

首先,它不会比java花费更长的时间,因为没有java对应物。java没有一个不变的列表。如果它有,性能将大致相同

其次,它需要很多时间,因为附加列表具有线性性能,所以整个过程具有二次性能


不是追加,而是预结束,它具有恒定的性能。

看起来您想使用Vector而不是List。List有O(1)个预结束,Vector有O(1)个追加。由于您是追加,但使用的是串联,所以使用Vector会更快:

def random: Double = java.lang.Math.random()
var f: Vector[Double] = Vector()
for (i <- 1 to 200000)
  f = f :+ (random*100)
def random:Double=java.lang.Math.random() 变量f:Vector[Double]=Vector()
对于(i)使用:::以这种方式,每次迭代都要重建整个列表。理想情况下,实际上应该使用惰性数据结构,但如果确实需要列表,请使用
f=(random*100)::f
也可以从
var f:list[Double]开始=Nil
-不需要定义random,只需导入它:
导入java.lang.Math.random
顺便说一句,
java.lang.Math.random()
不是特别随机的(请参见:)。一个好的选择(还有其他选择)是。还有一个
scala.util.Random
,不需要使用Java版本。@Jesper:是的。但是应该注意的是
scala.util.Random
只是
Java.util.Random()
的包装器。一个小的调整:val f=for(uuu感谢马丁,非常简洁明了的替代品。嘿,谢谢马丁,但我注意到了关于这个替代品的一些东西——如果我试图把这个名单传给一个演员,那就要花很长时间(超过20个替身的名单)-但是我的原始代码没有超过20码的列表。谢谢伯恩先生,你知道我为什么会死得这么惨吗?我想这是因为:::导致每次都生成一个新的列表,从而成为cpu上的杀手?是的,你是对的。你每次迭代都在重建整个列表。使用
math.random
,这就是answer我会给:)@Kevin:当然。改变了。我的借口是我通常用a来代替,不管怎样……这是一种标新立异的方式,“标新立异”是我创造的一个词,意思是“符合公认的标新立异习语”,与“Pythonic”平行,这是对任何被欣然接受的替代词的提名。@Malvolio:怎么样“Scalar?”:)@Malvolio:我指定“Scalaric”如果你的随机数倒过来真的很重要吗?谢谢。序列并不重要(在我的例子中),因为它们都将被传递给参与者进行选择排序。
def random: Double = java.lang.Math.random()
var f: Vector[Double] = Vector()
for (i <- 1 to 200000)
  f = f :+ (random*100)