Differenza tra un Seq e un elenco in Scala


299

Ho visto in molti esempi che a volte viene utilizzato un Seq, mentre altre volte è l'Elenco ...

C'è qualche differenza, a parte il fatto che il primo è un tipo Scala e l'Elenco proveniente da Java?

Risposte:


408

In termini Java, Scala Seqsarebbe Java Liste Scala Listsarebbe Java LinkedList.

Nota che Seqè un trait, che è equivalente a quello di Java interface, ma con l'equivalente di metodi difensivi emergenti. Scala Listè una classe astratta che viene estesa da Nile ::, che sono le implementazioni concrete di List.

Quindi, dove Java Listè un interface, Scala Listè un'implementazione.

Oltre a ciò, Scala Listè immutabile, il che non è il caso di LinkedList. In effetti, Java non ha equivalenti a raccolte immutabili (la sola lettura garantisce solo che il nuovo oggetto non può essere modificato, ma è comunque possibile cambiare quello vecchio e, quindi, quello "sola lettura").

Scala Listè altamente ottimizzato da compilatore e librerie ed è un tipo di dati fondamentale nella programmazione funzionale. Tuttavia, presenta delle limitazioni ed è inadeguato per la programmazione parallela. In questi giorni, Vectorè una scelta migliore di List, ma l'abitudine è difficile da rompere.

Seqè una buona generalizzazione per le sequenze, quindi se programmate interfacce, dovreste usarle. Nota che ci sono in realtà tre di loro: collection.Seq, collection.mutable.Seqe collection.immutable.Seq, ed è il secondo quello che è il "default" importato in ambito.

C'è anche GenSeqe ParSeq. Questi ultimi metodi funzionano in parallelo ove possibile, mentre il primo è genitore di entrambi Seqe ParSeq, essendo una generalizzazione adatta per quando il parallelismo di un codice non ha importanza. Sono entrambi introdotti relativamente di recente, quindi le persone non li usano ancora molto.


3
RE "Java non ha equivalenti alle raccolte immutabili" , sebbene Stringnon sia una raccolta, è un esempio di classi immutabili familiari ai programmatori Java.
huynhjl,

15
@huynhjl Questo è il punto. Stavo disegnando parallelismi tra ciò che esiste in Java e ciò che esiste in Scala, e in Java non esiste alcun concetto di raccolte mutabili / immutabili.
Daniel C. Sobral,

2
Java in realtà ha l'equivalente di raccolte immutabili. Non è così "ben pubblicizzato", ma è lì e quando si usano i generici pesantemente è probabile che colpisca alcuni a UnsupportedOperationExceptioncausa di questo. Per creare un elenco immutabile in Java usi il Collections.unmodifiableList () e allo stesso modo ci sono altri metodi per set, mappe ecc. Docs.oracle.com/javase/6/docs/api/java/util/…
jbx

27
@jbx Non è vero. Se usi questi metodi, ottieni qualcosa un oggetto che genererà eccezioni sui metodi che lo modificano, ma non un oggetto immutabile . Se l'oggetto originale viene modificato dopo la creazione dell'oggetto non modificabile, l'oggetto non modificabile lo rifletterà. Quindi, immodificabile, sì, immutabile, no.
Daniel C. Sobral,

3
@jbx Il metodo di ricezione non può mantenere un riferimento alla raccolta che ha ricevuto e supporre che non cambierà mai, e non esiste alcun tipo nella libreria Java standard che garantisca che - questa è immutabilità. Quindi, per esempio, quel metodo di ricezione non può garantire la sicurezza del thread. E questo non tocca nemmeno le caratteristiche persistenti rese possibili dall'immutabilità. Senza tutto ciò, non può essere definito "equivalente".
Daniel C. Sobral,

81

Un Seq è un Iterable che ha un ordine definito di elementi. Le sequenze forniscono un metodo apply()per l'indicizzazione, che va da 0 fino alla lunghezza della sequenza. Seq ha molte sottoclassi tra cui Coda, Intervallo, Elenco, Stack e LinkedList.

Un elenco è un Seq implementato come un elenco collegato immutabile. È meglio utilizzato nei casi con schemi di accesso last-in first-out (LIFO).

Ecco la gerarchia completa della classe di raccolta dalle FAQ di Scala :

inserisci qui la descrizione dell'immagine


2
Where Array (and ArrayBuffer)? Non è una specie di Iterable
Peter Krauss,

23

Seqè un tratto che Listimplementa.

Se si definisce il contenitore come Seq, è possibile utilizzare qualsiasi contenitore che implementa Seqtratto.

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

Nota che

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

È solo una scorciatoia per:

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

se il tipo di contenitore non è specificato, per impostazione predefinita la struttura dati sottostante List.


18

In Scala, un Elenco eredita da Seq, ma implementa Prodotto ; ecco la definizione corretta di Elenco :

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

[Nota: la definizione attuale è un po 'più complessa, al fine di adattarsi e utilizzare il potente framework di raccolta di Scala.]


0

Come diceva @ daniel-c-sobral, List estende il tratto Seq ed è una classe astratta implementata da scala.collection.immutable.$colon$colon(o ::in breve), ma a parte i tecnicismi, tieni presente che la maggior parte degli elenchi e dei seq che usiamo sono inizializzati nella forma di Seq(1, 2, 3)o List(1, 2, 3)che entrambi restituiscono scala.collection.immutable.$colon$colon, quindi si può scrivere:

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

Di conseguenza, direi che l'unica cosa che conta sono i metodi che vuoi esporre, ad esempio per anteporre puoi usare ::da Elenco che trovo ridondante con +:da Seq e mi attengo personalmente a Seq per impostazione predefinita.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.