我有一个我希望得到的序列:
val x = (1 to 1000000)
x.length
这是O(1)操作吗? (看起来像这样,在repl中尝试了几行。)为什么?什么是序列存储,使其成为O(1)操作,如果它是一个? (它只是将序列的长度存储为元数据吗?)
答案 0 :(得分:16)
(1 to 1000000)
创建一个Range
对象(不是更通用的Seq
)。 Range
通过调用length
来定义count
:
def count(start: Int, end: Int, step: Int, isInclusive: Boolean): Int = {
// faster path for the common counting range
if (start >= 0 && end > start && end < scala.Int.MaxValue && step == 1)
(end - start) + ( if (isInclusive) 1 else 0 )
else
NumericRange.count[Long](start, end, step, isInclusive)
}
因此,您可以看到,在给定的简单情况下,步长为1的Range
,length
为O(1),因为它只是减去end-start
并添加一个。 NumericRange.count
选项更复杂,但仍使用数学运算在常量时间内查找值。
至于其他Seq
类型:
List
是一个链表,不直接存储长度信息,因此需要遍历整个结构并跟踪它看到的元素数量:
def length: Int = {
var these = self
var len = 0
while (!these.isEmpty) {
len += 1
these = these.tail
}
len
}
另一方面,Vector
之类的东西存储索引信息,因此它可以在固定时间内返回长度:
def length = endIndex - startIndex
其他Seq
类型可能会以其他方式实现length
。
答案 1 :(得分:8)
这取决于Seq的实施。长度定义为抽象(http://www.scala-lang.org/api/current/scala/collection/Seq.html),因此某些序列可能是常量时间(如数组),有些可能是线性的(链接列表)。