这是my previous question的后续行动。
我知道我们可以使用streams
来生成'pi'(和其他数字),第n个斐波那契等的近似值。但我怀疑是否{{1}这是正确的方法。
主要缺点(我认为)是内存消耗:例如streams
将保留i <所有的斐波纳契数。我虽然只需要斐波纳契。当然,我可以使用stream
,但它使解决方案更复杂一些。 drop
看起来像是一种更适合这类任务的方法。
您怎么看?
答案 0 :(得分:1)
如果需要快速行驶,请轻装上阵。那意味着;避免分配任何不必要的内存。如果您需要内存,请使用可用的快速收集。如果你知道你需要多少记忆;预分配。分配是绝对的性能杀手......用于计算。你的代码可能看起来不太好了,但它会很快。
但是,如果您正在使用IO(磁盘,网络)或任何用户交互,那么分配就会失败。最好将优先级从代码性能转移到可维护性。
答案 1 :(得分:1)
使用Iterator。它不保留中间值。
答案 2 :(得分:1)
如果你想要第n个斐波纳契数并使用流作为临时数据结构(如果你不保留对先前计算的流元素的引用),那么你的算法将在恒定空间中运行。 之前计算的Stream元素(不再使用)将被垃圾收集。由于它们是在最年轻的一代中分配并立即收集的,因此所有分配都可能在缓存中。
更新:
似乎Stream的当前实现并不像它可能的那样节省空间,主要是因为它从LinearSeqOptimized trait继承了apply
方法的实现,其中它被定义为
def apply(n: Int): A = {
val rest = drop(n)
if (n < 0 || rest.isEmpty) throw new IndexOutOfBoundsException("" + n)
rest.head
}
此处由this
保留对流的头部的引用,并防止流被gc'ed。因此,drop
和head
方法的组合(如f.drop(100).head
)可能更适合丢弃中间结果的情况。 (感谢Sebastien Bocq在scala-user上解释这些内容)。