Ich werde meinen Kommentar etwas erweitern. Die List[T]
Datenstruktur von scala.collection.immutable
ist so optimiert, dass sie so funktioniert, wie eine unveränderliche Liste in einer rein funktionalen Programmiersprache. Es hat sehr schnelle Vorlaufzeiten und es wird davon ausgegangen, dass Sie für fast alle Ihre Zugriffe am Kopf arbeiten werden.
Unveränderliche Listen haben sehr schnelle Vorlaufzeiten, da sie ihre verknüpften Listen als eine Reihe von "Cons-Zellen" modellieren. Die Zelle definiert einen einzelnen Wert und einen Zeiger auf die nächste Zelle (klassischer einfach verknüpfter Listenstil):
Cell [Value| -> Nil]
Wenn Sie einer Liste voranstellen, erstellen Sie eigentlich nur eine einzelne neue Zelle, auf die der Rest der vorhandenen Liste verweist:
Cell [NewValue| -> [Cell[Value| -> Nil]]
Da die Liste unveränderlich ist, können Sie dies ohne Kopieren tun . Es besteht keine Gefahr, dass sich die alte Liste ändert und alle Werte in Ihrer neuen Liste ungültig werden. Als Kompromiss verlieren Sie jedoch die Möglichkeit, einen veränderlichen Zeiger auf das Ende Ihrer Liste zu setzen.
Dies eignet sich sehr gut für die rekursive Bearbeitung von Listen. Angenommen, Sie haben Ihre eigene Version von 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)
}
}
Dies ist eine rekursive Funktion, die ausschließlich vom Anfang der Liste aus funktioniert und den Pattern Matching über den :: Extractor nutzt. In Sprachen wie Haskell sieht man so viel.
Wenn Sie wirklich schnelle Anhänge wünschen, bietet Scala eine Vielzahl von veränderlichen und unveränderlichen Datenstrukturen zur Auswahl. Auf der veränderlichen Seite könnten Sie nachsehen ListBuffer
. Alternativ hat Vector
ab scala.collection.immutable
eine schnelle Append-Zeit.