Espanderò un po 'il mio commento. La List[T]
struttura dei dati, da scala.collection.immutable
è ottimizzata per funzionare come funziona un elenco immutabile in un linguaggio di programmazione più puramente funzionale. Ha tempi di prepend molto rapidi e si presume che lavorerai sulla testa per quasi tutto il tuo accesso.
Gli elenchi immutabili ottengono tempi di prepend molto rapidi a causa del fatto che modellano i loro elenchi collegati come una serie di "celle contro". La cella definisce un singolo valore e un puntatore alla cella successiva (stile classico dell'elenco a link singolo):
Cell [Value| -> Nil]
Quando anteponi a un elenco, stai davvero creando una singola nuova cella, con il resto dell'elenco esistente indicato:
Cell [NewValue| -> [Cell[Value| -> Nil]]
Poiché l'elenco è immutabile, puoi farlo senza alcuna copia effettiva . Non c'è pericolo che la vecchia lista cambi e causi l'invalidità di tutti i valori nella tua nuova lista. Tuttavia, si perde la possibilità di disporre di un puntatore modificabile alla fine dell'elenco come compromesso.
Questo si presta molto bene a lavorare ricorsivamente su liste. Supponiamo che tu abbia definito la tua versione di filter
:
def deleteIf[T](list : List[T])(f : T => Boolean): List[T] = list match {
case Nil => Nil
case (x::xs) => f(x) match {
case true => deleteIf(xs)(f)
case false => x :: deleteIf(xs)(f)
}
}
Questa è una funzione ricorsiva che funziona esclusivamente dalla testa dell'elenco e sfrutta la corrispondenza dei pattern tramite il :: extractor. Questo è qualcosa che vedi molto in lingue come Haskell.
Se vuoi davvero aggiungere rapidamente, Scala offre molte strutture di dati mutabili e immutabili tra cui scegliere. Sul lato mutevole, potresti esaminare ListBuffer
. In alternativa, Vector
da scala.collection.immutable
ha un tempo di aggiunta rapido.