2012-06-15 5 views
28

(prendilo come seguito a questa domanda - No Scala mutable list)Quale elenco di scala mutabile usare?

Voglio usare una lista mutabile in scala. Posso scegliere tra

che è bello, ma qual è il, raccomandata, via scala idiomatica "standard"? Voglio solo usare una lista alla quale posso aggiungere delle cose sul retro.

Edit:

OK, per espandere ulteriormente.

Sto usando un HashMap, dove i "liste" (sto significa che in senso generale) sarà sul lato valore. Poi, sto leggendo qualcosa da un file e per ogni riga, voglio trovare la lista giusta nella hashmap e aggiungere il valore alla lista.

+2

Probabilmente si dovrebbe espandere su come userete esso - perché in un senso generale, il modo in cui Scala idiomatica non è quello di utilizzare gli elenchi mutabili a tutti (anziché utilizzare pieghe o ricorsione con liste immutabili). –

+0

Penso che le tue liste possano essere immutabili. Puoi semplicemente anteporre un elenco immutabile e aggiornare la tua voce HashMap a quella appena creata. – ziggystar

+0

Bene, in tal caso, dovrò cambiare l'hashmap anziché gli elenchi. Al momento, non cambio l'hashmap, ma cambio le liste. –

risposta

14

Per i lettori che visitano questa vecchia domanda: La sezione della documentazione Concrete Mutable Collection Classes ha una panoramica delle classi di elenchi modificabili, comprese le spiegazioni su quando utilizzare quale.

+0

Oh fantastico! Sto pensando di accettare questa risposta, invece, 3 anni dopo –

+0

Accettato. Mi dispiace per @ axel22, ma ha fatto del suo meglio nel 2012 –

33

Dipende da ciò che ti serve.

DoubleLinkedList è una lista collegata che permette di attraversare avanti e indietro attraverso la lista dei nodi. Utilizzare i suoi riferimenti prev e next per passare rispettivamente al nodo precedente o successivo.

LinkedList è un elenco collegato singolarmente, quindi non ci sono i puntatori prev - se si attraversano sempre l'elemento successivo dell'elenco tutto il tempo, questo è ciò che è necessario.

EDIT: Si noti che i due sopra sono destinati ad essere utilizzati internamente come blocchi di costruzione per Strutture lista più complicati come MutableList s che supportano accodamento efficiente e mutable.Queue s.

Le due raccolte sopra entrambe hanno operazioni di accodamento in tempo lineare.

ListBuffer è una classe di buffer. Sebbene sia supportato da una struttura di dati di elenchi collegati singolarmente, non espone il puntatore next al client, quindi è possibile attraversarlo solo utilizzando gli iteratori e lo foreach. suo utilizzo principale è, tuttavia, come un buffer e un costruttore lista immutabile - si aggiunge elementi ad esso tramite +=, e quando si chiama result, è molto efficiente tornare funzionale immutable.List. A differenza delle liste mutabili e immutabili, entrambe le operazioni di accodamento e di antefatto sono a tempo costante - è possibile aggiungere alla fine tramite += in modo molto efficiente.

MutableList viene utilizzato internamente, di solito non lo si utilizza a meno che non si preveda di implementare una classe di raccolta personalizzata in base alla struttura di dati dell'elenco collegato separatamente. Ad esempio, le code mutabili ereditano questa classe. La classe MutableList ha anche un'efficiente operazione di aggiunta costante, poiché mantiene un riferimento all'ultimo nodo nell'elenco.

+0

Gli elenchi concatenati hanno davvero un'appendice lineare? Perché? Sia le liste singole che quelle doppie possono supportare append in un tempo costante, almeno nel mondo completamente mutabile. – svick

+0

Sì, lo fanno - vedere qui: https://github.com/scala/scala/blob/v2.9.2/src/library/scala/collection/mutable/LinkedListLike.scala#L1. Perché? La scelta progettuale è stato quello di rendere ogni nodo di una lista collegata di per sé - altrimenti si avrebbe bisogno di un wrapper per l'inizio e la fine riferimenti nodo, che è esattamente ciò che il 'MutableList' è. – axel22

+0

Non vedo una risposta nei documenti per "quale lista è la migliore per rimuovere elementi" ad es. se ho intenzione di costruire una lista, rimuovi una tonnellata di oggetti uno alla volta? – Hamy

9

Se si desidera aggiungere elementi che non si dovrebbe usare un List a tutti. List s sono buoni quando si desidera aggiungere gli elementi.Utilizzare invece ArrayBuffer.

+5

Non sono d'accordo. Se non hai bisogno dell'accesso casuale, 'ListBuffer' ha caratteristiche di performance migliori di' ArrayBuffer', che deve essere ridimensionato di volta in volta. Certo, le operazioni di aggiunta possono essere eseguite in * tempo di ammortamento * ammortizzato * o qualcosa del genere, che non è male, ma non vedo alcun vantaggio di 'ArrayBuffer' qui. – rolve

+5

@rolve Il tempo costante ammortizzato è spesso più veloce alla fine, perché le costanti coinvolte per l'allocazione di un nuovo oggetto sulla JVM (e la pressione associata del GC) sono piuttosto elevate, mentre le operazioni di ridimensionamento si verificano molto raramente (in media ogni elemento viene copiato due volte). Per non parlare dei vantaggi della localizzazione cache di ArrayBuffer, che può essere enorme sulle moderne CPU. –

+2

@JohnColanduoni Con quasi 3 anni trascorsi dal mio commento, sono d'accordo sul fatto che 'ArrayBuffer' è probabilmente la scelta migliore. In ogni caso, le misurazioni delle prestazioni effettive dovrebbero essere utilizzate come base per questa discussione. :) – rolve

2

Voglio solo utilizzare un elenco che è possibile aggiungere le cose sul retro.

Quindi scegliere qualcosa che implementa Growable. Personalmente suggerisco una delle implementazioni Buffer.

Rimango lontano da LinkedList e DoubleLinkedList, in quanto sono presenti principalmente come implementazione sottostante di altre raccolte, ma presentano alcuni bug fino a Scala 2.9.x. A partire da Scala 2.10.0, mi aspetto che le varie correzioni dei bug li abbiano portati allo standard. Tuttavia, mancano alcuni metodi che la gente si aspetta, come ad esempio +=, che troverete sulle raccolte basate su di essi.