Diferencia entre una secuencia y una lista en Scala

299

He visto en muchos ejemplos que a veces se usa un Seq, mientras que otras veces es la Lista ...

¿Hay alguna diferencia, aparte de que el primero es un tipo Scala y la Lista proviene de Java?

opensas
fuente

Respuestas:

408

En términos de Java, Scala Seqsería Java Listy Scala Listsería Java LinkedList.

Tenga en cuenta que Seqes una trait, que es equivalente a la de Java interface, pero con el equivalente de los métodos de defensa emergentes. Scala's Listes una clase abstracta que se extiende por Nily ::, que son implementaciones concretas de List.

Entonces, donde Java Listes interface, Scala Listes una implementación.

Más allá de eso, Scala's Listes inmutable, que no es el caso de LinkedList. De hecho, Java no tiene equivalente a colecciones inmutables (lo de solo lectura solo garantiza que el nuevo objeto no se puede cambiar, pero aún se puede cambiar el antiguo y, por lo tanto, el de "solo lectura").

Scala's Listestá altamente optimizado por el compilador y las bibliotecas, y es un tipo de datos fundamental en la programación funcional. Sin embargo, tiene limitaciones y es inadecuado para la programación paralela. En estos días, Vectores una mejor opción que List, pero el hábito es difícil de romper.

Seqes una buena generalización para secuencias, por lo que si programa en interfaces, debería usarla. Tenga en cuenta que en realidad hay tres de ellos: collection.Seq, collection.mutable.Seqy collection.immutable.Seq, y es este último que es el "default" importado a su alcance.

También hay GenSeqy ParSeq. Los últimos métodos se ejecutan en paralelo siempre que sea posible, mientras que el primero es padre de ambos Seqy ParSeq, siendo una generalización adecuada para cuando el paralelismo de un código no importa. Ambos son relativamente nuevos, por lo que la gente todavía no los usa mucho.

Daniel C. Sobral
fuente
3
RE "Java no tiene equivalente a colecciones inmutables" , aunque Stringno es una colección, es un ejemplo de clases inmutables familiares para los programadores de Java.
huynhjl
15
@huynhjl Eso no viene al caso. Estaba dibujando paralelos entre lo que existe en Java y lo que existe en Scala, y simplemente no hay ningún concepto de colecciones mutables / inmutables en Java.
Daniel C. Sobral
2
Java en realidad tiene el equivalente de colecciones inmutables. No es tan 'bien publicitado' pero está ahí y cuando usas genéricos en gran medida es probable que golpees algunos UnsupportedOperationExceptiondebido a esto. Para crear una lista inmutable en Java, use Collections.unmodifiableList () y, de manera similar, existen otros métodos para conjuntos, mapas, etc. docs.oracle.com/javase/6/docs/api/java/util/…
jbx
27
@jbx No es cierto. Si usa estos métodos, obtiene algo de un objeto que arrojará excepciones sobre los métodos que lo modifican, pero no un objeto inmutable . Si el objeto original se modifica después de que se creó el objeto no modificable, el objeto no modificable lo reflejará. Entonces, inmodificable, sí, inmutable, no.
Daniel C. Sobral
3
@jbx El método de recepción no puede mantener una referencia a la colección que recibió y supone que nunca cambiará, y no hay ningún tipo en la biblioteca Java estándar que garantice eso, eso es inmutabilidad. Entonces, por ejemplo, ese método de recepción no puede garantizar la seguridad del hilo. Y esto ni siquiera toca las características persistentes habilitadas por la inmutabilidad. Sin todo eso, no puede llamarse "equivalente".
Daniel C. Sobral
81

Un Seq es un Iterable que tiene un orden definido de elementos. Las secuencias proporcionan un método apply()para indexar, que van desde 0 hasta la longitud de la secuencia. Seq tiene muchas subclases que incluyen Cola, Rango, Lista, Pila y LinkedList.

Una Lista es una Seq que se implementa como una lista vinculada inmutable. Se utiliza mejor en casos con patrones de acceso de último en entrar, primero en salir (LIFO).

Aquí está la jerarquía de clases de colección completa de las preguntas frecuentes de Scala :

ingrese la descripción de la imagen aquí

Ceasar Bautista
fuente
2
Donde Array (y ArrayBuffer)? No es un poco Iterable
Peter Krauss
23

Seqes un rasgo que Listimplementa.

Si define su contenedor como Seq, puede usar cualquier contenedor que implemente Seqrasgo.

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

Tenga en cuenta que

scala> val a = Seq(1,2,3)
a: Seq[Int] = List(1, 2, 3)

Es solo una mano corta para:

scala> val a: Seq[Int] = List(1,2,3)
a: Seq[Int] = List(1, 2, 3)

si no se especifica el tipo de contenedor, la estructura de datos subyacente es la predeterminada List.

Akavall
fuente
18

En Scala, una Lista hereda de Seq, pero implementa Producto ; Aquí está la definición adecuada de Lista :

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

[Nota: la definición real es un poco más compleja, para encajar y utilizar el muy poderoso marco de colección de Scala.]

zakelfassi
fuente
0

Como dijo @ daniel-c-sobral, List extiende el rasgo Seq y es una clase abstracta implementada por scala.collection.immutable.$colon$colon(o ::para abreviar), pero aparte de los tecnicismos, tenga en cuenta que la mayoría de las listas y seqs que usamos se inicializan en forma de Seq(1, 2, 3)o List(1, 2, 3)ambas devuelven scala.collection.immutable.$colon$colon, por lo tanto, uno puede escribir:

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

Como resultado, diría que lo único que importa son los métodos que desea exponer, por ejemplo, para anteponer que puede usar ::de la Lista con la que considero redundante +:de Seq y personalmente me adhiero a Seq de forma predeterminada.

Profiterole
fuente