在Scala中,您将元素添加到不可变列表的方式如下:
val l = 1 :: 2 :: Nil
l: List[Int] = List(1, 2)
这意味着您首先创建一个Nil(空)列表,然后添加2然后再添加1.即这些操作是右关联的。所以,实际上,它可以以更清晰的方式重写,如下所示:
val l = (1 :: (2 :: Nil))
l: List[Int] = List(1, 2)
问题是,如果List应该保留插入顺序,并且如果首先将2添加到空列表然后添加1,那么为什么答案不是l: List[Int] = List(2, 1)
??
答案 0 :(得分:1)
这只是惯例。列表基本上是堆栈。访问或修改最近添加的项目效率最高。您也可以将列表的头部视为最终项目,在这种情况下,您建议的符号是合适的。
我推测这个约定的原因是我们通常不太关心列表的构建方式,但我们经常要考虑访问的第一个项目是订购中的初始项目,因此符号反映了这一点。
答案 1 :(得分:1)
这是因为元素是前置的:首先2
然后是1
。
从cons方法的定义:
def ::[B >: A] (x: B): List[B] =
new scala.collection.immutable.::(x, this)
在这里,您可以看到每次创建案例类scala.collection.immutable.::
的新实例时:
case class ::[B](val head: B, var tail: List[B]) extends List[B]
您只需将新元素用作head
作为新列表,将整个上一个列表用作tail
。
对不可变List
的前置操作也需要恒定时间O(1),追加为线性O(n)(来自Scala docs)。