Differenza tra array ed elenco in scala


142

In quali casi dovrei usare Array (Buffer) e List (Buffer). Solo una differenza che conosco è che gli array non sono variabili e gli elenchi sono covarianti. Ma per quanto riguarda le prestazioni e alcune altre caratteristiche?

Risposte:


155

Strutture immutabili

Scala Listè un'immutabile struttura di dati ricorsivi che è una struttura così fondamentale in Scala, che dovresti (probabilmente) usarla molto più di un Array(che è in realtà mutabile - l' analogo immutabile di Arrayis IndexedSeq).

Se si proviene da un background di Java, quindi l'ovvio parallelo è quando usare LinkedListsopra ArrayList. Il primo viene generalmente utilizzato per elenchi che vengono attraversati sempre e solo (e la cui dimensione non è nota in anticipo) mentre il secondo deve essere utilizzato per elenchi che hanno una dimensione nota (o dimensione massima) o per i quali è importante un accesso casuale rapido .

Strutture mutevoli

ListBufferfornisce una conversione a tempo costante in un Listmotivo che è la sola ragione da utilizzare ListBufferse è richiesta tale conversione successiva.

Uno scala Arraydovrebbe essere implementato sulla JVM da un array Java, e quindi un Array[Int]potrebbe essere molto più performante (come un int[]) di un List[Int](che impacchetterà il suo contenuto, a meno che tu non stia usando le ultime versioni di Scala che hanno la nuova @specializedfunzionalità) .

Tuttavia, penso che l'uso di Arrays in Scala dovrebbe essere ridotto al minimo perché sembra che tu debba davvero sapere cosa sta succedendo sotto il cofano per decidere se il tuo array sarà davvero supportato dal tipo primitivo richiesto, o potrebbe essere inscatolato come un tipo di wrapper.


vedi anche stackoverflow.com/questions/3213368/… e stackoverflow.com/questions/2481149/… la definizione di "uguale" per gli array è che si riferiscono allo stesso array
oluies

130

Oltre alle risposte già pubblicate, ecco alcuni dettagli.

Mentre an Array[A]è letteralmente un array Java, a List[A]è una struttura di dati immutabile che è Nil(l'elenco vuoto) o è costituito da una coppia (A, List[A]).

Differenze di prestazione

                          Array  List
Access the ith element    θ(1)   θ(i)
Delete the ith element    θ(n)   θ(i)
Insert an element at i    θ(n)   θ(i)
Reverse                   θ(n)   θ(n)
Concatenate (length m,n)  θ(n+m) θ(n)
Count the elements        θ(1)   θ(n)

Differenze di memoria

                          Array  List
Get the first i elements  θ(i)   θ(i)
Drop the first i elements θ(n-i) θ(1)
Insert an element at i    θ(n)   θ(i)
Reverse                   θ(n)   θ(n)
Concatenate (length m,n)  θ(n+m) θ(n)

Pertanto, a meno che non sia necessario un rapido accesso casuale, sia necessario contare gli elementi o, per qualche motivo, siano necessari aggiornamenti distruttivi, a Listè meglio di un Array.


Questi Os devono considerare il tempo per copiare l'elenco? Presumo che si sta facendo il test in questo modo, ad esempio: list = list.drop(i). Oppure, si verifica un po 'di magia dietro il cofano?

2
Ciò tiene conto della copia di elenchi e matrici quando necessario. Si noti che cose come dropnon è mai necessario copiare la parte dell'elenco che non è stata eliminata. Ad esempio , non (x::xs).drop(1)è esattamente xsuna "copia" di xs.
Apocalisp

6
Questi asintotici non hanno nulla a che fare con la Scala. La stessa struttura di dati in C sarà esattamente veloce fino a fattori costanti.
Apocalisp

1
@Apocalisp Hai un riferimento o a quali condizioni hai determinato queste informazioni?
Phil

1
@Phil Questi sono asintotici, non misurazioni. Saranno veri in tutte le condizioni.
Apocalisp,

18

Un array è mutabile, il che significa che è possibile modificare i valori di ciascun indice, mentre un elenco (per impostazione predefinita) è immutabile, il che significa che un nuovo elenco viene creato ogni volta che si esegue una modifica. Nella maggior parte dei casi si tratta di uno stile più "funzionale" di lavorare con tipi di dati immutabili e, probabilmente, si dovrebbe cercare di utilizzare una lista con i costrutti come yield, foreach, matche così via.

Per le caratteristiche prestazionali, un array è più veloce con accesso casuale agli elementi, mentre un elenco è più veloce quando si antepone (aggiungendo) nuovi elementi. Iterare su di essi è paragonabile.


@leonm - apols, ho pensato che l'OP chiedesse esclusivamente sulle classi * Buffer, mi rendo conto che stavano chiedendo anche quelle "normali"!
oxbow_lakes,

2
Di solito è più veloce aggiungere ad un ArrayBuffer piuttosto che anteporre a un Elenco (o aggiungere un elemento a un ListBuffer) poiché gli elenchi richiedono la creazione di un oggetto wrapper mentre ArrayBuffer deve semplicemente copiare l'oggetto (in media circa due volte) in un nuovo array . Due copie sono in genere più veloci della creazione di un oggetto, quindi l'appendice ArrayBuffer di solito batte anteporre List.
Rex Kerr,

array funziona molto più velocemente dell'elenco quando iterate over, a causa della cache
Bin
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.