2011-02-17 2 views
9

questa è una domanda un po 'generale, ma mi chiedevo se qualcuno potesse consigliarmi su quali sarebbero i vantaggi di lavorare con gli array vs arrayseq. Da quello che ho visto Array è la rappresentazione di scala degli array java e non ci sono troppi membri nella sua api mentre Arrayseq sembra contenere una api molto più ricca. grazie per qualsiasi consiglioscala - array vs arrayseq

risposta

32

In realtà ci sono quattro classi diverse si poteva scegliere per ottenere la funzionalità array come mutabile.

Array + ArrayOps 
WrappedArray 
ArraySeq 
ArrayBuffer 

Array è un semplice array Java vecchio. È di gran lunga il modo migliore per accedere a un basso livello agli array di primitivi. Non ci sono spese generali. Inoltre può agire come le collezioni Scala grazie alla conversione implicita in ArrayOps, che acquisisce l'array sottostante, applica il metodo appropriato e, se appropriato, restituisce un nuovo array. Ma dal momento che lo ArrayOps non è specializzato per le primitive, è lento (è lento quanto il boxing/unboxing è sempre).

WrappedArray è un semplice array Java vecchio, ma racchiuso in tutte le chicche della collezione di Scala. La differenza tra questo e è WrappedArray restituisce un altro WrappedArray - così almeno non si ha il sovraccarico di dover ri-ArrayOps la matrice primitiva Java più e più volte per ogni operazione. È buono da usare quando stai facendo un sacco di interop con Java e devi passare in semplici vecchi array Java, ma sul lato Scala devi manipolarli convenientemente.

ArraySeq memorizza i dati in un semplice vecchio array Java, ma non memorizza più le matrici di primitive; tutto è una matrice di oggetti. Ciò significa che i primitivi vengono incassati mentre entrano. Questo è davvero conveniente se si vogliono usare i primitivi molte volte; dal momento che hai memorizzato le copie in scatola, devi solo cancellarle, non metterle in scatola e rimuoverle su ogni operazione generica.

ArrayBuffer si comporta come un array, ma è possibile aggiungere e rimuovere elementi da esso. Se andrai fino a ArraySeq, perché non hai la flessibilità aggiuntiva di cambiare lunghezza mentre ci sei?

+0

questo dovrebbe essere parte di ogni (e qualsiasi) scala documentazione intorno alle collezioni. +1 – Dragonborn

0

Come hai osservato correttamente, ArraySeq ha un'API più ricca in quanto deriva da IndexedSeq (e così via) mentre Array è una rappresentazione diretta di array Java.

La relazione tra entrambi potrebbe essere approssimativamente paragonata alla relazione di ArrayList e matrici in Java.

A causa dell'API, è consigliabile utilizzare ArraySeq a meno che non vi sia un motivo specifico per non farlo. Usando toArray(), puoi convertire in qualsiasi momento una matrice.

+2

Non così! Hanno la [stessa API ...] (http://www.scala-lang.org/api/current/scala/collection/mutable/ArrayLike.html) –

+0

Ah, non ho visto la conversione implicita –

6

Dalle scala-lang.org forum:

Array [T] - Vantaggi: Nativo, veloce - Limitazioni: alcuni metodi (si applicano solo, aggiornamento, la lunghezza), ha bisogno di sapere a T di compilazione tempo, perché Java bytecode rappresenta (char [] diverso da int [] diverso da Object [])

ArraySeq [T] (classe precedentemente noto come GenericArray [T]): - Vantaggi: ancora supportato da un array nativo, non è necessario per sapere nulla su T a compile-time (nuovo ArraySeq [T] "solo funziona", anche se non è nulla conosciuto circa T), suite completa di metodi SeqLike, sottotipo di Seq [T] - Limitazioni: E ' sostenuta da un array [AnyRef], indipendentemente di ciò che T è (se T è primitiva, quindi elementi saranno inscatolati/unboxed su loro modo dentro o fuori del supporto Array)


ArraySeq [Qualsiasi] è molto più veloce di Array [Qualsiasi] durante la manipolazione primitive. In qualsiasi codice si dispone di matrice [T], dove T non è <: AnyRef, è possibile ottenere prestazioni più veloci da ArraySeq.

+2

Sicuramente avere quello indietro - come dice la tua citazione, scatole ArraySeq e primitive di unboxes. –

+0

@Jim - Così fa 'Array [Any]', lo fa solo più lentamente. Per ottenere le prestazioni da 'Array' deve essere digitato come' Array [Int] ', o qualsiasi altra primitiva che stai effettivamente utilizzando. –

+0

@Kevin Ma ha detto "In qualsiasi codice hai Array [T], dove T non è <: AnyRef, otterrai prestazioni più veloci da ArraySeq" ... che non è vero se T è Int. –

8

Array è una rappresentazione diretta di Java di Array, e utilizza la stessa bytecode sulla JVM.

Il vantaggio di Array è che è l'unico tipo di raccolta sulla JVM per non subire cancellazione del tipo, array sono anche in grado di tenere direttamente primitive senza boxe, questo li può rendere molto veloce in alcune circostanze.

Inoltre, si ottiene il comportamento di covarianza dell'array su array incasinato di Java. (Se passi ad es.un Array[Int] a qualche classe Java che può essere assegnato ad una variabile di tipo Array[Object] che poi gettare un ArrayStoreException sul tentativo di aggiungere tutto ciò che non è un int.)

ArraySeq è usato raramente al giorno d'oggi, è più di una storica artefatto dalle versioni precedenti di Scala che trattava gli array in modo diverso. Visto che devi comunque occuparti della boxe, sei quasi certo di scoprire che un altro tipo di collezione è più adatto alle tue esigenze.

In caso contrario ... Le matrici hanno esattamente la stessa API di ArraySeq, grazie a una conversione implicita da Array a ArrayOps.

A meno che non si abbia un'esigenza specifica per le proprietà uniche degli array, provare ad evitarli. Vedere This Talk at around 19:30 o This Article per un'idea del tipo di problemi che gli Array possono introdurre.

Dopo aver visto quel video, è interessante notare che Scala usa Seq per varargs :)