Unterschied zwischen einer Seq und einer Liste in Scala

299

Ich habe in vielen Beispielen gesehen, dass manchmal eine Seq verwendet wird, während manchmal die Liste ...

Gibt es einen Unterschied, außer dass der erste ein Scala-Typ ist und die Liste aus Java stammt?

opensas
quelle

Antworten:

408

In Java-Begriffen Seqwäre Scala Java Listund Scala ListJava LinkedList.

Beachten Sie, dass dies a Seqist trait, was Java entspricht interface, aber dem Äquivalent aufstrebender Verteidigungsmethoden entspricht. Scala's Listist eine abstrakte Klasse, die um Nilund erweitert wird und ::deren konkrete Implementierungen sind List.

Wo also Java Listist interface, ist Scala Listeine Implementierung.

Darüber hinaus ist Scala Listunveränderlich, was bei nicht der Fall ist LinkedList. Tatsächlich hat Java keine Entsprechung zu unveränderlichen Sammlungen (das schreibgeschützte Element garantiert nur, dass das neue Objekt nicht geändert werden kann, Sie können jedoch das alte und daher das schreibgeschützte Objekt ändern).

Scala's Listwird von Compilern und Bibliotheken stark optimiert und ist ein grundlegender Datentyp in der funktionalen Programmierung. Es hat jedoch Einschränkungen und ist für die parallele Programmierung nicht geeignet. Heutzutage Vectorist es eine bessere Wahl als List, aber Gewohnheit ist schwer zu brechen.

Seqist eine gute Verallgemeinerung für Sequenzen. Wenn Sie also auf Schnittstellen programmieren, sollten Sie diese verwenden. Beachten Sie, dass es tatsächlich drei davon gibt : collection.Seq, collection.mutable.Seqund collection.immutable.Seq, und es ist das letztere, das der "Standard" ist, der in den Bereich importiert wird.

Es gibt auch GenSeqund ParSeq. Die letzteren Methoden werden nach Möglichkeit parallel ausgeführt, während die ersteren beiden übergeordnet sind Seqund ParSeqeine geeignete Verallgemeinerung darstellen, wenn die Parallelität eines Codes keine Rolle spielt. Sie sind beide relativ neu eingeführt, so dass die Leute sie noch nicht viel benutzen.

Daniel C. Sobral
quelle
3
RE "Java hat kein Äquivalent zu unveränderlichen Sammlungen" , obwohl Stringes keine Sammlung ist, ist es ein Beispiel für unveränderliche Klassen, die Java-Programmierern vertraut sind.
Huynhjl
15
@huynhjl Das ist nebensächlich. Ich habe Parallelen zwischen dem, was in Java existiert, und dem, was in Scala existiert, gezogen, und es gibt einfach kein Konzept für veränderbare / unveränderliche Sammlungen in Java.
Daniel C. Sobral
2
Java hat tatsächlich das Äquivalent von unveränderlichen Sammlungen. Es ist nicht so gut beworben, aber es ist da und wenn Sie Generika stark verwenden, werden Sie wahrscheinlich einige davon treffen UnsupportedOperationException. Um eine unveränderliche Liste in Java zu erstellen, verwenden Sie Collections.unmodutableList (). Ebenso gibt es andere Methoden für Sets, Maps usw. docs.oracle.com/javase/6/docs/api/java/util/…
jbx
27
@jbx Nicht wahr. Wenn Sie diese Methoden verwenden, erhalten Sie ein Objekt, das Ausnahmen für Methoden auslöst, die es ändern, jedoch kein unveränderliches Objekt. Wenn das ursprüngliche Objekt geändert wird, nachdem das nicht veränderbare Objekt erstellt wurde, spiegelt das nicht veränderbare Objekt dies wider. Also, unveränderlich, ja, unveränderlich, nein.
Daniel C. Sobral
3
@jbx Die Empfangsmethode kann keinen Verweis auf die empfangene Sammlung behalten und davon ausgehen, dass sie sich niemals ändern wird, und es gibt keinen Typ in der Standard-Java-Bibliothek, der dies garantiert - das ist Unveränderlichkeit. So kann diese Empfangsmethode beispielsweise die Thread-Sicherheit nicht garantieren. Und dies berührt nicht einmal die beständigen Eigenschaften, die durch Unveränderlichkeit ermöglicht werden. Ohne all das kann es nicht als "äquivalent" bezeichnet werden.
Daniel C. Sobral
81

Eine Seq ist eine Iterable mit einer definierten Reihenfolge von Elementen. Sequenzen bieten eine Methode apply()zur Indizierung, die von 0 bis zur Länge der Sequenz reicht. Seq hat viele Unterklassen, einschließlich Queue, Range, List, Stack und LinkedList.

Eine Liste ist eine Sequenz, die als unveränderliche verknüpfte Liste implementiert ist. Es wird am besten in Fällen mit LIFO-Zugriffsmustern (Last-In First-Out) verwendet.

Hier ist die vollständige Hierarchie der Sammlungsklassen aus den Scala-FAQ :

Geben Sie hier die Bildbeschreibung ein

Ceasar Bautista
quelle
2
Wo Array (und ArrayBuffer)? Es ist nicht irgendwie Iterable
Peter Krauss
23

Seqist eine Eigenschaft, die Listimplementiert.

Wenn Sie Ihren Container als definieren Seq, können Sie jeden Container verwenden, der das SeqMerkmal implementiert .

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

Beachten Sie, dass

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

Ist nur eine kurze Hand für:

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

Wenn der Containertyp nicht angegeben ist, wird standardmäßig die zugrunde liegende Datenstruktur verwendet List.

Akavall
quelle
18

In Scala erbt eine Liste von Seq, implementiert jedoch Product . Hier ist die richtige Definition von Liste :

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

[Hinweis: Die eigentliche Definition ist etwas komplexer, um in das sehr leistungsstarke Sammlungsframework von Scala zu passen und es zu nutzen.]

zakelfassi
quelle
0

Wie @ daniel-c-sobral sagte, erweitert List das Merkmal Seq und ist eine abstrakte Klasse, die von scala.collection.immutable.$colon$colon(oder ::kurz) implementiert wird. Abgesehen von den technischen Aspekten ist jedoch zu beachten, dass die meisten von uns verwendeten Listen und Seqs in Form von Seq(1, 2, 3)oder von List(1, 2, 3)beiden zurückgegeben werden scala.collection.immutable.$colon$colondaher kann man schreiben:

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

Infolgedessen würde ich argumentieren, dass das einzige, was zählt, die Methoden sind, die Sie verfügbar machen möchten, zum Beispiel, um vorab zu verwenden, dass Sie ::aus der Liste verwenden können, mit der ich +:aus Seq überflüssig bin, und ich persönlich halte mich standardmäßig an Seq.

Profiterole
quelle