Różnica między Sekwencją a Listą w Scali

299

Widziałem w wielu przykładach, że czasami używa się Seq, podczas gdy innym razem jest Lista ...

Czy jest jakaś różnica, poza tym, że poprzedni to Scala i Lista pochodząca z Javy?

opensas
źródło

Odpowiedzi:

408

Mówiąc językiem Java, Scala należałaby do SeqJavy List, a Scala należałaby do ListJavy LinkedList.

Zauważ, że Seqjest traitto odpowiednik Javy interface, ale z odpowiednimi metodami obrońcy. Scala Listto klasa abstrakcyjna, która jest rozszerzana przez Nili ::, które są konkretnymi implementacjami List.

Tak więc, tam gdzie Java Listjest interface, Scala Listjest implementacją.

Poza tym Scala's Listjest niezmienny, co nie jest prawdą LinkedList. W rzeczywistości Java nie ma odpowiednika niezmiennych kolekcji (tylko do odczytu gwarantuje tylko, że nowego obiektu nie można zmienić, ale nadal można zmienić stary, a zatem „tylko do odczytu”).

Scala Listjest wysoce zoptymalizowany przez kompilator i biblioteki i jest podstawowym typem danych w programowaniu funkcjonalnym. Ma jednak ograniczenia i nie nadaje się do programowania równoległego. Te dni Vectorto lepszy wybór List, ale nawyk jest trudny do przełamania.

Seqjest dobrym uogólnieniem dla sekwencji, więc jeśli programujesz interfejsy, powinieneś tego użyć. Należy pamiętać, że tak naprawdę są trzy z nich: collection.Seq, collection.mutable.Seqi collection.immutable.Seq, i to jest ten ostatni, który jest „default” importowane do zakresu.

Jest też GenSeqi ParSeq. Te ostatnie metody działają równolegle tam, gdzie to możliwe, podczas gdy te pierwsze są nadrzędne dla obu Seqi ParSeqsą odpowiednim uogólnieniem, gdy równoległość kodu nie ma znaczenia. Oba są stosunkowo nowo wprowadzone, więc ludzie jeszcze ich nie używają.

Daniel C. Sobral
źródło
3
RE „Java nie ma odpowiednika niezmiennych kolekcji” , chociaż Stringnie jest zbiorem, jest przykładem klas niezmiennych znanych programistom Java.
huynhjl
15
@huynhjl To nie ma sensu. Rysowałem podobieństwa między tym, co istnieje w Javie, a tym, co istnieje w Scali, i po prostu nie ma żadnej koncepcji mutowalnych / niezmiennych zbiorów w Javie.
Daniel C. Sobral
2
Java faktycznie ma odpowiednik niezmiennych kolekcji. Nie jest to „dobrze reklamowane”, ale jest tam i kiedy intensywnie używasz leków generycznych, prawdopodobnie trafisz kilka UnsupportedOperationExceptionz tego powodu. Aby utworzyć niezmienną listę w Javie, użyj Collect.unmodifiableList
jbx
27
@jbx Nieprawda. Jeśli użyjesz tych metod, otrzymasz coś, co spowoduje wyjątki od metod, które je modyfikują, ale nie będzie to obiekt niezmienny . Jeśli oryginalny obiekt zostanie zmodyfikowany po utworzeniu obiektu niemodyfikowalnego, obiekt niemodyfikowalny to odzwierciedli. Więc niemodyfikowalne, tak, niezmienne, nie.
Daniel C. Sobral
3
@jbx Metoda odbierająca nie może zachować odwołania do kolekcji, którą otrzymała i założyć, że nigdy się nie zmieni, i nie ma żadnego typu w standardowej bibliotece Java, która by to zagwarantowała - to jest niezmienność. Na przykład ta metoda odbioru nie może zagwarantować bezpieczeństwa wątków. I to nawet nie dotyka trwałych cech niezmienności. Bez tego wszystkiego nie można go nazwać „równoważnym”.
Daniel C. Sobral
81

Sekwencyjny jest iterowalny który posiada określoną kolejność elementów. Sekwencje zapewniają metodę apply()indeksowania, od 0 do długości sekwencji. Seq ma wiele podklas, w tym Kolejkę, Zakres, Listę, Stos i LinkedList.

Lista jest sekwencyjny, który jest zaimplementowany jako niezmiennej listy powiązanej. Najlepiej stosować go w przypadkach z wzorcami dostępu „ostatni na wejściu” (LIFO).

Oto pełna hierarchia klas kolekcji z FAQ Scala :

wprowadź opis zdjęcia tutaj

Ceasar Bautista
źródło
2
Gdzie Array (i ArrayBuffer)? To nie jest rodzaj Iterable
Peter Krauss,
23

Seqjest cechą, która się Listimplementuje.

Jeśli zdefiniujesz swój kontener jako Seq, możesz użyć dowolnego kontenera, który implementuje Seqcechę.

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

Zauważ, że

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

To tylko krótka ręka dla:

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

jeśli typ kontenera nie jest określony, domyślna struktura danych podstawowych to List.

Akavall
źródło
18

W Scali lista dziedziczy po Seq, ale implementuje produkt ; oto właściwa definicja Listy :

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

[Uwaga: rzeczywista definicja . Jest odrobinę nieco bardziej skomplikowane, aby dopasować się i korzystać z bardzo mocnym ramach kolekcji Scala]

zakelfassi
źródło
0

Jak powiedział @ daniel-c-sobral, List rozszerza cechę Seq i jest klasą abstrakcyjną zaimplementowaną przez scala.collection.immutable.$colon$colon(lub ::w skrócie), ale pomijając kwestie techniczne, pamiętaj, że większość używanych przez nas list i sekwencji jest inicjowana w formie Seq(1, 2, 3)lub List(1, 2, 3)które obie zwracają scala.collection.immutable.$colon$colon, stąd można napisać:

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

W związku z tym argumentowałbym, że jedyne, co się liczy, to metody, które chcesz ujawnić, na przykład, aby przygotować się do użycia ::z Listy, które uważam za zbędne z +:Seq i osobiście domyślnie trzymam się Seq.

Profiterole
źródło