Différence entre Array et List dans scala

142

Dans quels cas je devrais utiliser Array (Buffer) et List (Buffer). La seule différence que je connais est que les tableaux ne sont pas variables et que les listes sont covariantes. Mais qu'en est-il des performances et de certaines autres caractéristiques?

Jeriho
la source

Réponses:

155

Structures immuables

La Scala Listest une structure de données récursive immuable qui est une structure si fondamentale dans Scala, que vous devriez (probablement) l'utiliser beaucoup plus qu'un Array(qui est en fait mutable - l' analogue immuable de Arrayis IndexedSeq).

Si vous venez d'un arrière-plan Java, le parallèle évident est de savoir quand utiliser LinkedListover ArrayList. Le premier est généralement utilisé pour les listes qui ne sont parcourues que jamais (et dont la taille n'est pas connue à l'avance) tandis que le second doit être utilisé pour les listes qui ont une taille connue (ou une taille maximale) ou pour lesquelles un accès aléatoire rapide est important.

Structures mutables

ListBufferfournit une conversion à temps constant en un Listqui est la seule raison à utiliser ListBuffersi une telle conversion ultérieure est requise.

Un scala Arraydoit être implémenté sur la JVM par un tableau Java, et donc un Array[Int]peut être beaucoup plus performant (en tant que int[]) qu'un List[Int](qui encapsulera son contenu, sauf si vous utilisez les toutes dernières versions de Scala qui ont la nouvelle @specializedfonctionnalité) .

Cependant, je pense que l'utilisation de Arrays dans Scala devrait être réduite au minimum car il semble que vous ayez vraiment besoin de savoir ce qui se passe sous le capot pour décider si votre tableau sera vraiment soutenu par le type primitif requis, ou peut être emballé comme un type d'emballage.

oxbow_lakes
la source
voir aussi stackoverflow.com/questions/3213368/… et stackoverflow.com/questions/2481149/… la définition de «égal» pour les tableaux est qu'ils se réfèrent au même tableau
oluies
130

En plus des réponses déjà publiées, voici quelques détails.

Alors que an Array[A]est littéralement un tableau Java, a List[A]est une structure de données immuable qui est soit Nil(la liste vide), soit constituée d'une paire (A, List[A]).

Différences de performances

                          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)

Différences de mémoire

                          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)

Donc, à moins que vous n'ayez besoin d'un accès aléatoire rapide, que vous ayez besoin de compter des éléments ou que, pour une raison quelconque, vous ayez besoin de mises à jour destructrices, un Listest mieux qu'un Array.

Apocalisp
la source
Ces OS doivent-ils considérer le temps de copier la liste? Je suppose que vous faites le test comme celui - ci, par exemple: list = list.drop(i). Ou, se produit-il de la magie derrière le capot?
2
Cela prend en compte la copie de listes et de tableaux si nécessaire. Notez que des choses comme dropne doivent jamais copier la partie de la liste qui n'a pas été supprimée. Par exemple, (x::xs).drop(1)est exactement xs, pas une "copie" de xs.
Apocalisp le
6
Ces asymptotiques n'ont absolument rien à voir avec Scala. La même structure de données en C sera exactement aussi rapide jusqu'à des facteurs constants.
Apocalisp
1
@Apocalisp Avez-vous une référence ou dans quelles conditions avez-vous déterminé cette information?
Phil
1
@Phil Ce sont des asymptotiques, pas des mesures. Ils resteront vrais dans toutes les conditions.
Apocalisp
18

Un tableau est modifiable, ce qui signifie que vous pouvez modifier les valeurs de chaque index, tandis qu'une liste (par défaut) est immuable, ce qui signifie qu'une nouvelle liste est créée à chaque fois que vous effectuez une modification. Dans la plupart des cas , il est un style plus « fonctionnel » à travailler avec des types de données immuables et vous devriez probablement essayer d'utiliser une liste avec des constructions comme yield, foreach, matchet ainsi de suite.

Pour les caractéristiques de performances, un tableau est plus rapide avec un accès aléatoire aux éléments, tandis qu'une liste est plus rapide lors de l'ajout de nouveaux éléments. Les itérer est comparable.

leonm
la source
@leonm - apols, je pensais que l'OP posait des questions exclusivement sur les classes * Buffer, je me rends compte qu'ils posaient également des questions sur les classes "normales"!
oxbow_lakes
2
Il est généralement plus rapide d'ajouter à un ArrayBuffer que de l'ajouter à une liste (ou d'ajouter un élément à un ListBuffer) car les listes nécessitent la création d'un objet wrapper tandis qu'ArrayBuffer a simplement besoin de copier l'objet (en moyenne environ deux fois) dans un nouveau tableau . Deux copies sont généralement plus rapides que la création d'un objet, donc ArrayBuffer append bat généralement List prepend.
Rex Kerr
le tableau fonctionne beaucoup plus rapidement que la liste lorsque iterate over, à cause du cache
Bin