Différence entre une séquence et une liste dans Scala

299

J'ai vu dans de nombreux exemples que parfois une Seq est utilisée, tandis que d'autres fois est la liste ...

Y a-t-il une différence, autre que l'ancien étant un type Scala et la liste venant de Java?

opensas
la source

Réponses:

408

En termes Java, Scala Seqserait Java Listet Scala Listserait JavaLinkedList .

Notez que Seqc'est un trait, qui est équivalent à Java interface, mais avec l'équivalent des méthodes de défense montantes. Scala Listest une classe abstraite qui est étendue par Nilet ::, qui sont les implémentations concrètes de List.

Ainsi, lorsque Java Listest un interface, Scala Listest une implémentation.

Au-delà de cela, Scala Listest immuable, ce qui n'est pas le cas de LinkedList. En fait, Java n'a pas d'équivalent aux collections immuables (la chose en lecture seule garantit que le nouvel objet ne peut pas être changé, mais vous pouvez toujours changer l'ancien et, par conséquent, celui en "lecture seule").

Scala Listest hautement optimisé par le compilateur et les bibliothèques, et c'est un type de données fondamental dans la programmation fonctionnelle. Cependant, il a des limites et est inadéquat pour la programmation parallèle. De nos jours, Vectorc'est un meilleur choix List, mais l'habitude est difficile à briser.

Seqest une bonne généralisation pour les séquences, donc si vous programmez sur des interfaces, vous devriez l'utiliser. Notez qu'il existe en fait trois d'entre eux: collection.Seq, collection.mutable.Seqet collection.immutable.Seq, et il est celui - ci qui est le « défaut » importé dans le périmètre.

Il y a aussi GenSeqet ParSeq. Ces dernières méthodes fonctionnent en parallèle lorsque cela est possible, tandis que la première est parent des deux Seqet ParSeq, étant une généralisation appropriée lorsque le parallélisme d'un code n'a pas d'importance. Ils sont tous deux relativement récents, donc les gens ne les utilisent pas encore beaucoup.

Daniel C. Sobral
la source
3
RE "Java n'a pas d'équivalent aux collections immuables" , bien qu'il Stringne s'agisse pas d'une collection, c'est un exemple de classes immuables familières aux programmeurs Java.
huynhjl
15
@huynhjl C'est à côté du point. Je faisais des parallèles entre ce qui existe en Java et ce qui existe en Scala, et il n'y a tout simplement pas de concept de collections mutables / immuables en Java.
Daniel C.Sobral
2
Java a en fait l'équivalent de collections immuables. Ce n'est pas si «bien annoncé» mais c'est là et lorsque vous utilisez beaucoup de génériques, vous risquez d'en frapper à UnsupportedOperationExceptioncause de cela. Pour créer une liste immuable en Java, vous utilisez Collections.unmodifiableList () et de même il existe d'autres méthodes pour les ensembles, les cartes, etc. docs.oracle.com/javase/6/docs/api/java/util/…
jbx
27
@jbx Pas vrai. Si vous utilisez ces méthodes, vous obtenez quelque chose un objet qui lèvera des exceptions sur les méthodes qui le modifient, mais pas un objet immuable . Si l'objet d'origine est modifié après la création de l'objet non modifiable, l'objet non modifiable le reflétera. Donc, non modifiable, oui, immuable, non.
Daniel C.Sobral
3
@jbx La méthode de réception ne peut pas garder une référence à la collection qu'elle a reçue et suppose qu'elle ne changera jamais, et il n'y a aucun type dans la bibliothèque Java standard qui garantira que - c'est l'immuabilité. Ainsi, par exemple, cette méthode de réception ne peut garantir la sécurité des threads. Et cela ne touche même pas aux caractéristiques persistantes permises par l'immuabilité. Sans tout cela, il ne peut pas être qualifié d '"équivalent".
Daniel C.Sobral
81

Un Seq est un Iterable qui a un ordre défini d'éléments. Les séquences fournissent une méthode apply()d'indexation, allant de 0 à la longueur de la séquence. Seq possède de nombreuses sous-classes, notamment Queue, Range, List, Stack et LinkedList.

Une liste est une séquence qui est implémentée en tant que liste liée immuable. Il est préférable de l'utiliser dans les cas avec des modèles d'accès dernier entré, premier sorti (LIFO).

Voici la hiérarchie complète des classes de collection de la FAQ Scala :

entrez la description de l'image ici

Ceasar Bautista
la source
2
Où Array (et ArrayBuffer)? Ce n'est pas du genre Iterable
Peter Krauss
23

Seqest un trait qui Listmet en œuvre.

Si vous définissez votre conteneur comme Seq, vous pouvez utiliser n'importe quel conteneur qui implémente Seqtrait.

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

Notez que

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

Est juste une main courte pour:

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

si le type de conteneur n'est pas spécifié, la structure de données sous-jacente est par défaut List.

Akavall
la source
18

Dans Scala, une List hérite de Seq, mais implémente Product ; voici la bonne définition de List :

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

[Remarque: la définition actuelle est un peu plus complexe, afin de s'intégrer et d'utiliser le cadre de collecte très puissant de Scala.]

zakelfassi
la source
0

Comme l'a dit @ daniel-c-sobral, List étend le trait Seq et est une classe abstraite implémentée par scala.collection.immutable.$colon$colon(ou ::pour faire court), mais à part les détails techniques, gardez à l'esprit que la plupart des listes et des séquences que nous utilisons sont initialisées sous la forme de Seq(1, 2, 3)ou List(1, 2, 3)qui retournent toutes les deux scala.collection.immutable.$colon$colon, on peut donc écrire:

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

En conséquence, je dirais que la seule chose qui importe, ce sont les méthodes que vous souhaitez exposer, par exemple pour ajouter au début, vous pouvez utiliser à ::partir de List que je trouve redondant avec +:de Seq et je persiste personnellement à Seq par défaut.

Profiterole
la source