【问题标题】:Difference between a Seq and a List in ScalaScala 中 Seq 和 List 的区别
【发布时间】:2012-06-07 15:51:07
【问题描述】:

我在许多示例中看​​到,有时使用 Seq,而其他时候使用 List...

除了前者是Scala类型和List来自Java之外,有什么区别吗?

【问题讨论】:

    标签: list scala collections seq


    【解决方案1】:

    在 Java 术语中,Scala 的 Seq 将是 Java 的 List,Scala 的 List 将是 Java 的 LinkedList

    注意Seq 是一个trait,相当于Java 的interface,但相当于新兴的防御者方法。 Scala的List是一个抽象类,由Nil::扩展而来,它们是List的具体实现。

    所以,Java 的 Listinterface,Scala 的 List 是一个实现。

    除此之外,Scala 的List 是不可变的,LinkedList 的情况并非如此。事实上,Java 没有不可变集合的等价物(只读的东西只保证新对象不能更改,但您仍然可以更改旧对象,因此是“只读”对象)。

    Scala 的List 经过编译器和库的高度优化,是函数式编程中的基本数据类型。但是,它有局限性,不足以进行并行编程。如今,Vector 是比List 更好的选择,但习惯很难改掉。

    Seq 是序列的一个很好的泛化,所以如果你编程到接口,你应该使用它。注意实际上有三个:collection.Seqcollection.mutable.Seqcollection.immutable.Seq,而后一个是“默认”导入作用域的。

    还有GenSeqParSeq。后一种方法在可能的情况下并行运行,而前者是SeqParSeq 的父类,当代码的并行性无关紧要时,这是一个合适的概括。它们都是相对较新推出的,所以人们还没有太多使用它们。

    【讨论】:

    • RE “Java 没有不可变集合的等价物”,虽然String 不是集合,但它是 Java 程序员熟悉的不可变类的示例。
    • @huynhjl 这不是重点。我在 Java 中存在的内容和 Scala 中存在的内容之间进行了比较,而 Java 中没有任何可变/不可变集合的概念。
    • Java 实际上具有不可变集合的等价物。它不是那么“宣传得很好”,但它在那里,当你大量使用泛型时,你可能会因此而打一些UnsupportedOperationException。要在 Java 中创建不可变列表,您可以使用 Collections.unmodifiableList() 类似地,还有其他方法用于 Sets、Maps 等。docs.oracle.com/javase/6/docs/api/java/util/…
    • @jbx 不正确。如果你使用这些方法,你会得到一个对象,它会在修改它的方法上抛出异常,而不是一个 immutable 对象。如果原始对象在不可修改对象创建后被修改,不可修改对象将反映这一点。所以,不可修改,是的,不可变的,不。
    • @jbx 接收方法不能保留对它接收到的集合的引用并假定它永远不会改变,并且标准 Java 库中没有类型可以保证——即不变性。因此,例如,该接收方法不能保证线程安全。这甚至没有触及由不变性启用的持久性特征。没有这一切,它不能被称为“等效”。
    【解决方案2】:

    Seq 是具有已定义元素顺序的 Iterable。序列提供了一种方法apply()进行索引,范围从0到序列的长度。 Seq 有很多子类,包括 Queue、Range、List、Stack 和 LinkedList。

    List 是一个作为不可变链表实现的 Seq。它最适用于具有后进先出 (LIFO) 访问模式的情况。

    这是来自Scala FAQ 的完整集合类层次结构:

    【讨论】:

    • Array(和 ArrayBuffer)在哪里?它不是一种可迭代的
    • This answer 显示数组
    【解决方案3】:

    SeqList 实现的特征。

    如果您将容器定义为Seq,则可以使用任何实现Seq trait 的容器。

    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

    【讨论】:

      【解决方案4】:

      在 Scala 中,List 继承自 Seq,但实现了Product;这是List的正确定义:

      sealed abstract class List[+A] extends AbstractSeq[A] with Product with ...
      

      [注意:the actual definition 稍微复杂一点,以适应和利用 Scala 非常强大的集合框架。]

      【讨论】:

        【解决方案5】:

        正如@daniel-c-sobral 所说,List 扩展了 trait Seq 并且是由 scala.collection.immutable.$colon$colon(或简称为 ::)实现的抽象类,但抛开技术问题,请注意我们使用的大多数列表和 seq以Seq(1, 2, 3)List(1, 2, 3) 的形式初始化,它们都返回scala.collection.immutable.$colon$colon,因此可以这样写:

        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]]
        

        因此,我认为唯一重要的是您要公开的方法,例如,您可以使用 List 中的 ::,我认为与 Seq 中的 +: 和我个人无关默认情况下坚持 Seq。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2015-02-13
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-05-22
          • 2020-07-20
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多