我是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
答案 0 :(得分:21)
你也可以这样做:
List.fill(200000)(math.random)
同样适用于数组......
Array.fill(200000)(math.random)
等等......
答案 1 :(得分:9)
你可以构建一个无限的随机双打流:
def randomList(): Stream[Double] = Stream.cons(math.random, randomList)
val f = randomList().take(200000)
这将利用延迟评估,因此在您真正需要之前不会计算值。即使评估所有200,000,也会很快。另外,f
不再需要var
。
答案 2 :(得分:7)
另一种可能性是:
val it = Iterator.continually(math.random)
it.take(200000).toList
如果您愿意, Stream
也有continually
方法。
答案 3 :(得分:5)
首先,它没有比java更长的时间,因为没有java对应物。 Java没有不可变列表。如果确实如此,表现将大致相同。
其次,由于附加列表具有线性性能,因此花费了大量时间,因此整个事物具有二次性能。
而不是附加,前置,具有持续的性能。
答案 4 :(得分:4)
如果你使用可变状态,你应该使用像缓冲区这样的可变集合,你也可以用+=
添加它(那时它将是真正的对应于java代码)。
但为什么不使用列表理解?
val f = for (_ <- 1 to 200000) yield (math.random * 100)
顺便说一下:var f = List(0.0)
... f = f.tail
可以在您的示例中替换为var f: List[Double] = Nil
。 (没有更多的表现,但更美丽;)
答案 5 :(得分:2)
还有更多选择!尾递归:
def randlist(n: Int, part: List[Double] = Nil): List[Double] = {
if (n<=0) part
else randlist(n-1, 100*random :: part)
}
或映射范围:
(1 to 200000).map(_ => 100*random).toList
答案 6 :(得分:1)
看起来您想要使用Vector而不是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)
知道了吗?