我在许多例子中看到,有时使用Seq,而其他时候使用List……
除了前者是Scala类型,而List来自Java之外,还有什么区别吗?
我在许多例子中看到,有时使用Seq,而其他时候使用List……
除了前者是Scala类型,而List来自Java之外,还有什么区别吗?
在Scala中,List继承了Seq,但实现了Product;下面是List的正确定义:
sealed abstract class List[+A] extends AbstractSeq[A] with Product with ...
[注意:实际的定义稍微复杂一点,为了适应并利用Scala非常强大的集合框架。]
在Java术语中,Scala的Seq就是Java的List, Scala的List就是Java的LinkedList。
请注意,Seq是一个特性,它类似于Java的接口,但与正在崛起的防御方法相当。Scala的List是一个抽象类,由Nil和::扩展,它们是List的具体实现。
所以,Java的List是一个接口,而Scala的List是一个实现。
除此之外,Scala的List是不可变的,这与LinkedList不同。事实上,Java没有与不可变集合等价的东西(只读的东西只能保证新对象不能被更改,但您仍然可以更改旧对象,因此,“只读”的对象也可以更改)。
Scala的List通过编译器和库进行了高度优化,它是函数式编程中的基本数据类型。但是,它有局限性,对于并行编程是不够的。如今,Vector是比List更好的选择,但习惯很难改掉。
Seq是序列的一个很好的泛化,所以如果你为接口编程,你应该使用它。请注意,实际上有三个:集合。Seq, collection。mutable。Seq和collection。immutable。Seq,而后者是导入作用域的“默认”。
还有GenSeq和ParSeq。后一种方法在可能的情况下并行运行,而前者是Seq和ParSeq的父方法,适用于不考虑代码并行性的情况。它们都相对较新,所以人们不怎么使用它们。
Seq是一个具有定义的元素顺序的Iterable。序列提供了apply()方法用于索引,范围从0到序列的长度。Seq有很多子类,包括Queue、Range、List、Stack和LinkedList。
List是实现为不可变链表的Seq。它最好用于后进先出(LIFO)访问模式的情况。
下面是Scala FAQ中完整的集合类层次结构:
Seq是List实现的一个特性。
如果将容器定义为Seq,则可以使用任何实现Seq特性的容器。
scala> def sumUp(s: Seq[Int]): Int = { s.sum }
sumUp: (s: Seq[Int])Int
scala> sumUp(List(1,2,3))
res41: Int = 6
scala> sumUp(Vector(1,2,3))
res42: Int = 6
scala> sumUp(Seq(1,2,3))
res44: Int = 6
请注意,
scala> val a = Seq(1,2,3)
a: Seq[Int] = List(1, 2, 3)
只是简称:
scala> val a: Seq[Int] = List(1,2,3)
a: Seq[Int] = List(1, 2, 3)
如果未指定容器类型,则底层数据结构默认为List。
正如@daniel-c-sobral所说,List扩展了trait Seq,是一个由scala.collection.immutable实现的抽象类。$colon$colon(或简称::),但抛开技术细节不考虑,请注意,我们使用的大多数列表和Seq都是以Seq(1,2,3)或List(1,2,3)的形式初始化的,它们都返回scala.collection.immutable。$冒号,因此可以这样写:
var x: scala.collection.immutable.$colon$colon[Int] = null
x = Seq(1, 2, 3).asInstanceOf[scala.collection.immutable.$colon$colon[Int]]
x = List(1, 2, 3).asInstanceOf[scala.collection.immutable.$colon$colon[Int]]
因此,我认为唯一重要的是你想要公开的方法,例如,你可以使用::from List,我发现+:from Seq是多余的,我个人默认坚持使用Seq。