获得序列的长度是一个恒定时间操作?

时间:2012-01-17 03:17:18

标签: scala

我有一个我希望得到的序列:

val x = (1 to 1000000)
x.length

这是O(1)操作吗? (看起来像这样,在repl中尝试了几行。)为什么?什么是序列存储,使其成为O(1)操作,如果它是一个? (它只是将序列的长度存储为元数据吗?)

2 个答案:

答案 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的Rangelength为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),因此某些序列可能是常量时间(如数组),有些可能是线性的(链接列表)。