J'ai toujours été du genre à simplement utiliser:
List<String> names = new ArrayList<>();
J'utilise l'interface comme nom de type pour la portabilité , de sorte que lorsque je pose des questions comme celles-ci, je puisse retravailler mon code.
Quand faut- LinkedList
il l'utiliser plus ArrayList
et vice-versa?
java
arraylist
collections
linked-list
sdellysse
la source
la source
Réponses:
Les résumés
ArrayList
avecArrayDeque
sont préférables dans beaucoup plus de cas d'utilisation queLinkedList
. Si vous n'êtes pas sûr, commencez parArrayList
.LinkedList
etArrayList
sont deux implémentations différentes de l'interface List.LinkedList
l'implémente avec une liste doublement liée.ArrayList
l'implémente avec un tableau de redimensionnement dynamique.Comme pour les opérations de liste chaînée et de tableau standard, les différentes méthodes auront des temps d'exécution algorithmiques différents.
Pour
LinkedList<E>
get(int index)
est O (n) (avec n / 4 pas en moyenne), mais O (1) quandindex = 0
ouindex = list.size() - 1
(dans ce cas, vous pouvez également utilisergetFirst()
etgetLast()
). L'un des principaux avantages deLinkedList<E>
add(int index, E element)
est O (n) (avec n / 4 pas en moyenne), mais O (1) quandindex = 0
ouindex = list.size() - 1
(dans ce cas, vous pouvez également utiliseraddFirst()
etaddLast()
/add()
). L'un des principaux avantages deLinkedList<E>
remove(int index)
est O (n) (avec n / 4 pas en moyenne), mais O (1) quandindex = 0
ouindex = list.size() - 1
(dans ce cas, vous pouvez également utiliserremoveFirst()
etremoveLast()
). L'un des principaux avantages deLinkedList<E>
Iterator.remove()
est O (1) . L'un des principaux avantages deLinkedList<E>
ListIterator.add(E element)
est O (1) . L'un des principaux avantages deLinkedList<E>
Remarque: De nombreuses opérations nécessitent en moyenne n / 4 étapes, un nombre constant d'étapes dans le meilleur des cas (par exemple, index = 0) et n / 2 étapes dans le pire des cas (milieu de la liste)
Pour
ArrayList<E>
get(int index)
est O (1) . Principal avantage deArrayList<E>
add(E element)
est O (1) amorti, mais O (n) dans le pire des cas puisque le tableau doit être redimensionné et copiéadd(int index, E element)
est O (n) (avec n / 2 pas en moyenne)remove(int index)
est O (n) (avec n / 2 pas en moyenne)Iterator.remove()
est O (n) (avec n / 2 pas en moyenne)ListIterator.add(E element)
est O (n) (avec n / 2 pas en moyenne)Remarque: la plupart des opérations nécessitent en moyenne n / 2 étapes, nombre d'étapes constant dans le meilleur des cas (fin de liste), n étapes dans le pire des cas (début de liste)
LinkedList<E>
permet des insertions ou des suppressions à temps constant à l' aide d'itérateurs , mais uniquement un accès séquentiel aux éléments. En d'autres termes, vous pouvez parcourir la liste en avant ou en arrière, mais trouver une position dans la liste prend du temps proportionnel à la taille de la liste. Javadoc dit que "les opérations qui indexent dans la liste traverseront la liste du début ou de la fin, selon ce qui est le plus proche" , donc ces méthodes sont O (n) ( n / 4 étapes) en moyenne, bien que O (1) pourindex = 0
.ArrayList<E>
, d'autre part, permettent un accès en lecture aléatoire rapide, de sorte que vous pouvez saisir n'importe quel élément en temps constant. Mais ajouter ou retirer de n'importe où mais la fin nécessite de déplacer tous ces derniers éléments, soit pour faire une ouverture soit pour combler l'écart. De plus, si vous ajoutez plus d'éléments que la capacité du tableau sous-jacent, un nouveau tableau (1,5 fois la taille) est alloué et l'ancien tableau est copié dans le nouveau, donc l'ajout à unArrayList
est O (n) dans le pire cas mais constant en moyenne.Ainsi, selon les opérations que vous envisagez de faire, vous devez choisir les implémentations en conséquence. Itérer sur l'un ou l'autre type de liste est pratiquement aussi bon marché. (Itérer sur un
ArrayList
est techniquement plus rapide, mais à moins que vous ne fassiez quelque chose de vraiment sensible aux performances, vous ne devriez pas vous en préoccuper - ce sont deux constantes.)Les principaux avantages de l'utilisation de a
LinkedList
surviennent lorsque vous réutilisez des itérateurs existants pour insérer et supprimer des éléments. Ces opérations peuvent ensuite être effectuées dans O (1) en modifiant la liste localement uniquement. Dans une liste de tableaux, le reste du tableau doit être déplacé (c'est-à-dire copié). D'un autre côté, la recherche d'unLinkedList
moyen suivant les liens dans O (n) ( n / 2 étapes) pour le pire des cas, alors que dans uneArrayList
position souhaitée peut être calculée mathématiquement et accessible dans O (1) .Un autre avantage de l'utilisation de a
LinkedList
survient lorsque vous ajoutez ou supprimez de la tête de la liste, car ces opérations sont O (1) , alors qu'elles sont O (n) pourArrayList
. Notez que celaArrayDeque
peut être une bonne alternative à l'LinkedList
ajout et au retrait de la tête, mais ce n'est pas unList
.De plus, si vous avez de grandes listes, gardez à l'esprit que l'utilisation de la mémoire est également différente. Chaque élément d'un
LinkedList
a plus de surcharge, car les pointeurs vers les éléments suivants et précédents sont également stockés.ArrayLists
n'ont pas ces frais généraux. Cependant,ArrayLists
occupez autant de mémoire que celle allouée à la capacité, que des éléments aient été réellement ajoutés ou non.La capacité initiale par défaut d'un
ArrayList
est assez petite (10 de Java 1.4 - 1.8). Mais comme l'implémentation sous-jacente est un tableau, le tableau doit être redimensionné si vous ajoutez beaucoup d'éléments. Pour éviter le coût élevé du redimensionnement lorsque vous savez que vous allez ajouter beaucoup d'éléments, construisez leArrayList
avec une capacité initiale plus élevée.la source
O(n/2)
ouO(n/4)
. La grande notation O vous indique comment une opération évolue avec un n plus grand . et une opération nécessitant desn/2
étapes évolue exactement comme une opération nécessitant desn
étapes, ce qui explique pourquoi les sommations ou facteurs constants sont supprimés.O(n/2)
etO(n/4)
sont tous deux justesO(n)
.LinkedList
etArrayList
ont de toute façon différents facteurs constants, de sorte qu'il ne serait pas logique de comparer l'unO(n/2)
de l'un avecO(n/4)
l'autre, les deux dénotent simplement des opérations de mise à l'échelle linéaire.Jusqu'à présent, personne ne semble avoir abordé l'empreinte mémoire de chacune de ces listes en plus du consensus général selon lequel a
LinkedList
est "beaucoup plus" qu'un anArrayList
, j'ai donc effectué un certain nombre de calculs pour démontrer exactement combien les deux listes occupent pour N références nulles.Étant donné que les références sont soit 32 ou 64 bits (même lorsqu'elles sont nulles) sur leurs systèmes relatifs, j'ai inclus 4 ensembles de données pour 32 et 64 bits
LinkedLists
etArrayLists
.Remarque: Les tailles indiquées pour les
ArrayList
lignes sont pour les listes découpées - En pratique, la capacité du tableau de sauvegarde dans unArrayList
est généralement plus grande que son nombre d'éléments actuel.Remarque 2: (merci BeeOnRope) Comme CompressedOops est désormais par défaut à partir du milieu de JDK6 et plus, les valeurs ci-dessous pour les machines 64 bits correspondront fondamentalement à leurs homologues 32 bits, à moins bien sûr que vous ne les désactiviez spécifiquement.
Le résultat montre clairement que
LinkedList
c'est beaucoup plus que celaArrayList
, surtout avec un nombre d'éléments très élevé. Si la mémoire est un facteur, évitez-leLinkedLists
.Les formules que j'ai utilisées suivent, faites-moi savoir si j'ai fait quelque chose de mal et je vais le réparer. «b» est soit 4 ou 8 pour les systèmes 32 ou 64 bits, et «n» est le nombre d'éléments. Notez que la raison des mods est que tous les objets en java prendront un multiple de 8 octets, qu'ils soient tous utilisés ou non.
Liste des tableaux:
ArrayList object header + size integer + modCount integer + array reference + (array oject header + b * n) + MOD(array oject, 8) + MOD(ArrayList object, 8) == 8 + 4 + 4 + b + (12 + b * n) + MOD(12 + b * n, 8) + MOD(8 + 4 + 4 + b + (12 + b * n) + MOD(12 + b * n, 8), 8)
LinkedList:
LinkedList object header + size integer + modCount integer + reference to header + reference to footer + (node object overhead + reference to previous element + reference to next element + reference to element) * n) + MOD(node object, 8) * n + MOD(LinkedList object, 8) == 8 + 4 + 4 + 2 * b + (8 + 3 * b) * n + MOD(8 + 3 * b, 8) * n + MOD(8 + 4 + 4 + 2 * b + (8 + 3 * b) * n + MOD(8 + 3 * b, 8) * n, 8)
la source
int
, donc 4 ou 8 octets de données. Dans la liste chaînée, il y a essentiellement 4 "mots" de surcharge. Votre graphique donne ainsi l'impression que les listes liées utilisent "cinq fois" le stockage des listes de tableaux. C'est faux. La surcharge est de 16 ou 32 octets par objet, en tant qu'ajustement additif, et non comme facteur d'échelle.CompressedOops
est maintenant par défaut dans tous les JDKs récents (7, 8 et mises à jour de 6 pour quelques années), de sorte que 64 bits ne sera pas faire une différence dansArrayList
ouLinkedList
tailles, à moins que vous avez explicitement désactivé oops comprimé pour quelque raison.ArrayList
sans spécifier de capacité initiale, il utilisera toujours beaucoup moins de mémoire qu'unLinkedList
.ArrayList
c'est ce que tu veux.LinkedList
est presque toujours un bogue (de performance).Pourquoi
LinkedList
suce:ArrayList
étaient utilisés.ArrayList
, il sera probablement beaucoup plus lent de toute façon.LinkedList
dans la source car c'est probablement le mauvais choix.la source
En tant que personne qui fait de l'ingénierie de performance opérationnelle sur des services Web SOA à très grande échelle depuis environ une décennie, je préférerais le comportement de LinkedList à ArrayList. Alors que le débit en régime permanent de LinkedList est pire et pourrait donc conduire à acheter plus de matériel - le comportement d'ArrayList sous pression pourrait conduire les applications d'un cluster à étendre leurs baies en quasi synchronicité et pour les grandes tailles de baies pourrait conduire à un manque de réactivité dans l'application et une panne, sous pression, ce qui est un comportement catastrophique.
De même, vous pouvez obtenir un meilleur débit dans une application à partir du ramasse-miettes par défaut, mais une fois que vous obtenez des applications java avec des tas de 10 Go, vous pouvez finir par verrouiller l'application pendant 25 secondes pendant un GC complet, ce qui provoque des délais d'attente et des échecs dans les applications SOA et souffle vos SLA si cela se produit trop souvent. Même si le collecteur CMS prend plus de ressources et n'atteint pas le même débit brut, c'est un bien meilleur choix car il a une latence plus prévisible et plus petite.
ArrayList n'est un meilleur choix pour les performances que si tout ce que vous entendez par performances est le débit et que vous pouvez ignorer la latence. D'après mon expérience dans mon travail, je ne peux pas ignorer la pire latence.
la source
LinkedList
toujours cinq fois plus de mémoire qu'un simple tableau de références, donc unArrayList
2,5 fois temporairement nécessaire consomme toujours beaucoup moins de mémoire, même si la mémoire n'est pas récupérée. Étant donné que l'allocation de grandes baies contourne l'espace Eden, elles n'ont aucun impact sur le comportement du GC, à moins qu'il n'y ait vraiment pas assez de mémoire, auquel cas, elles ontLinkedList
explosé beaucoup plus tôt…LinkedList
n'a besoin que d'un petit morceau de mémoire libre pour allouer à l'élément suivant.ArrayList
aura besoin d'un grand espace libre et continu pour allouer le tableau redimensionné. Si le tas est fragmenté, le GC peut finir par réorganiser le tas entier juste pour libérer un seul bloc de mémoire approprié.Algorithmes: notation Big-Oh
Les listes de tableaux sont bonnes pour les écritures à lecture unique ou les ajouteurs, mais mauvaises pour ajouter / supprimer à l'avant ou au milieu.
la source
O(1)
. Il doit parcourir la moitié de la liste pour trouver le point d'insertion.LinkedList
estO(1)
si vous avez un itérateur à la position d'insertion , c'estListIterator.add
-à- dire est censé êtreO(1)
pour unLinkedList
.Oui, je sais, c'est une question ancienne, mais je vais mettre mes deux cents:
LinkedList est presque toujours le mauvais choix, en termes de performances. Il existe des algorithmes très spécifiques pour lesquels une LinkedList est requise, mais ceux-ci sont très, très rares et l'algorithme dépend généralement spécifiquement de la capacité de LinkedList à insérer et supprimer des éléments au milieu de la liste relativement rapidement, une fois que vous y avez navigué. avec un ListIterator.
Il existe un cas d'utilisation courant dans lequel LinkedList surpasse ArrayList: celui d'une file d'attente. Cependant, si votre objectif est la performance, au lieu de LinkedList, vous devriez également envisager d'utiliser un ArrayBlockingQueue (si vous pouvez déterminer à l'avance une limite supérieure sur la taille de votre file d'attente et pouvez vous permettre d'allouer toute la mémoire à l'avance), ou cette implémentation CircularArrayList . (Oui, il s'agit de 2001, vous devrez donc le générer, mais j'ai obtenu des ratios de performances comparables à ceux cités dans l'article dans une récente JVM)
la source
ArrayDeque
. docs.oracle.com/javase/6/docs/api/java/util/ArrayDeque.htmlArrayDeque
est plus lent qu'àLinkedList
moins que toutes les opérations soient à la même fin. C'est OK lorsqu'il est utilisé comme une pile mais cela ne fait pas une bonne file d'attente.ArrayDeque
est susceptible d'être plus rapide queStack
lorsqu'il est utilisé comme une pile, et plus rapide queLinkedList
lorsqu'il est utilisé comme une file d'attente.ArrayDeque
documentation.C'est une question d'efficacité.
LinkedList
est rapide pour ajouter et supprimer des éléments, mais lent pour accéder à un élément spécifique.ArrayList
est rapide pour accéder à un élément spécifique mais peut être lent à ajouter aux deux extrémités, et particulièrement lent à supprimer au milieu.Array vs ArrayList vs LinkedList vs Vector va plus en profondeur, tout comme la liste liée .
la source
Correct ou incorrect: veuillez exécuter le test localement et décider par vous-même!
Modifier / Supprimer est plus rapide
LinkedList
queArrayList
.ArrayList
, soutenu parArray
, qui doit être le double de la taille, est pire dans les applications à grand volume.Vous trouverez ci-dessous le résultat du test unitaire pour chaque opération. La synchronisation est donnée en nanosecondes.
Voici le code:
la source
LinkedList
a beaucoup plus de mémoire car pour chaque élément il y a un objet nœud avec cinq champs. Sur de nombreux systèmes, cela représente une surcharge de 20 octets. La surcharge de mémoire moyenne par élément pourArrayList
est un mot et demi, ce qui fait 6 octets et 8 octets dans le pire des cas.removeIf(element -> condition)
où il convient, ce qui peut être considérablement plus rapide pour anArrayList
, par rapport au bouclage et à la suppression via l'itérateur, car il n'est pas nécessaire de déplacer le reste entier pour chaque élément individuel. Que cela fonctionne mieux ou moins bien que celaLinkedList
dépend du scénario particulier, commeLinkedList
est O (1) en théorie, mais la suppression d'un seul nœud nécessite plusieurs accès à la mémoire, ce qui peut facilement dépasser le nombre nécessaire pour laArrayList
lors de la suppression d'un nombre significatif d'éléments .ArrayList
est essentiellement un tableau.LinkedList
est implémenté comme une double liste chaînée.C'est
get
assez clair. O (1) pourArrayList
, carArrayList
autoriser l'accès aléatoire à l'aide de l'index. O (n) pourLinkedList
, car il doit d'abord trouver l'index. Remarque: il existe différentes versions deadd
etremove
.LinkedList
est plus rapide à ajouter et à supprimer, mais plus lent à obtenir. En bref,LinkedList
devrait être préféré si:=== ArrayList ===
=== LinkedList ===
ajouter (E e)
add (index int, élément E)
Voici une figure de programcreek.com (
add
etremove
sont le premier type, c'est-à-dire, ajoutez un élément à la fin de la liste et supprimez l'élément à la position spécifiée dans la liste.):la source
Joshua Bloch, l'auteur de LinkedList:
Lien: https://twitter.com/joshbloch/status/583813919019573248
Je suis désolé que la réponse ne soit pas aussi informative que les autres réponses, mais je pensais que ce serait la plus intéressante et la plus explicite.
la source
ArrayList
est accessible au hasard, alors qu'ilLinkedList
est vraiment bon marché de développer et de supprimer des éléments. Dans la plupart des cas,ArrayList
c'est bien.À moins d'avoir créé de grandes listes et mesuré un goulot d'étranglement, vous n'aurez probablement jamais à vous soucier de la différence.
la source
TL; DR en raison de l'architecture informatique moderne,
ArrayList
sera considérablement plus efficace pour presque tous les cas d'utilisation possibles - etLinkedList
doit donc être évité, sauf dans certains cas très uniques et extrêmes.En théorie, LinkedList a un O (1) pour le
add(E element)
L'ajout d'un élément au milieu d'une liste devrait également être très efficace.
La pratique est très différente, puisque LinkedList est une structure de cache de données hostiles . Du POV de performance - il y a très peu de cas où les
LinkedList
performances pourraient être meilleures que celles compatibles avec le cacheArrayList
.Voici les résultats d'un test de référence insérant des éléments dans des emplacements aléatoires. Comme vous pouvez le voir - la liste des tableaux est beaucoup plus efficace, bien qu'en théorie chaque insertion au milieu de la liste nécessite de "déplacer" les n derniers éléments du tableau (les valeurs inférieures sont meilleures):
Travailler sur un matériel de dernière génération (caches plus gros et plus efficaces) - les résultats sont encore plus concluants:
LinkedList prend beaucoup plus de temps pour accomplir le même travail. code source source
Il y a deux raisons principales pour cela:
Principalement - que les nœuds du
LinkedList
sont dispersés au hasard dans la mémoire. La RAM ("Random Access Memory") n'est pas vraiment aléatoire et des blocs de mémoire doivent être récupérés pour être mis en cache. Cette opération prend du temps, et lorsque ces récupérations se produisent fréquemment - les pages de mémoire dans le cache doivent être remplacées tout le temps -> Le cache manque -> Le cache n'est pas efficace.ArrayList
les éléments sont stockés dans une mémoire continue, ce qui est exactement ce que l'architecture CPU moderne optimise.Secondaire
LinkedList
requis pour retenir les pointeurs arrière / avant, ce qui signifie 3 fois la consommation de mémoire par valeur stockée par rapport àArrayList
.DynamicIntArray , btw, est une mise en œuvre personnalisée d'ArrayList
Int
(type primitif) et non des objets - par conséquent, toutes les données sont réellement stockées de manière adjacente - donc encore plus efficace.Un élément clé à retenir est que le coût de l'extraction d'un bloc de mémoire est plus important que le coût d'accès à une seule cellule de mémoire. C'est pourquoi le lecteur 1 Mo de mémoire séquentielle est jusqu'à 400 fois plus rapide que la lecture de cette quantité de données à partir de différents blocs de mémoire:
Source: chiffres de latence que chaque programmeur devrait connaître
Juste pour rendre le point encore plus clair, veuillez vérifier la référence de l'ajout d'éléments au début de la liste. C'est un cas d'utilisation où, en théorie, le
LinkedList
devrait vraiment briller, etArrayList
devrait présenter des résultats médiocres ou pire encore:Remarque: il s'agit d'une référence de la bibliothèque C ++ Std, mais mon expérience précédente a montré que les résultats C ++ et Java sont très similaires. Code source
Copier une masse séquentielle de mémoire est une opération optimisée par les processeurs modernes - changer la théorie et rendre, encore une fois,
ArrayList
/Vector
beaucoup plus efficaceCrédits: Tous les benchmarks publiés ici sont créés par Kjell Hedström . Encore plus de données peuvent être trouvées sur son blog
la source
Si votre code a
add(0)
etremove(0)
, utilisez unLinkedList
et c'est plus joliaddFirst()
et desremoveFirst()
méthodes. Sinon, utilisezArrayList
.Et bien sûr, Guava 's ImmutableList est votre meilleur ami.
la source
Je sais que c'est un ancien poste, mais honnêtement, je ne peux pas croire que personne n'ait mentionné qu'il
LinkedList
implémenteDeque
. Regardez simplement les méthodes dansDeque
(etQueue
); si vous voulez une comparaison juste, essayez de courirLinkedList
contreArrayDeque
et faites une comparaison fonctionnalité par fonctionnalité.la source
Voici la notation Big-O à la fois
ArrayList
etLinkedList
et aussiCopyOnWrite-ArrayList
:Liste des tableaux
LinkedList
CopyOnWrite-ArrayList
Sur cette base, vous devez décider quoi choisir. :)
la source
LinkedList.add()
, bien que la plupart des réponses ici le disent.Comparons LinkedList et ArrayList par rapport aux paramètres ci-dessous:
1. Mise en œuvre
2. Performance
get (int index) ou opération de recherche
La raison pour laquelle ArrayList est plus rapide que LinkedList est que ArrayList utilise un système basé sur un index pour ses éléments car il utilise en interne une structure de données de tableau, d'autre part,
LinkedList ne fournit pas d'accès basé sur l'index pour ses éléments car il itère depuis le début ou la fin (selon ce qui est le plus proche) pour récupérer le nœud à l'index d'élément spécifié.
opération insert () ou add (Object)
supprimer l'opération (int)
L'opération de suppression dans LinkedList est généralement la même que ArrayList, c'est-à-dire O (n).
3. Itérateur inversé
4. Capacité initiale
5. Overhead mémoire
La source
la source
J'utilise habituellement l'un sur l'autre en fonction de la complexité temporelle des opérations que j'effectuerais sur cette liste particulière.
la source
En plus des autres bons arguments ci-dessus, vous devriez remarquer l' interface
ArrayList
implementsRandomAccess
, tandis queLinkedList
implementsQueue
.Donc, d'une manière ou d'une autre, ils abordent des problèmes légèrement différents, avec des différences d'efficacité et de comportement (voir leur liste de méthodes).
la source
Cela dépend des opérations que vous effectuerez le plus sur la liste.
ArrayList
est plus rapide pour accéder à une valeur indexée. C'est bien pire lors de l'insertion ou de la suppression d'objets.Pour en savoir plus, lisez tout article qui parle de la différence entre les tableaux et les listes liées.
la source
Une liste de tableaux est essentiellement un tableau avec des méthodes pour ajouter des éléments, etc. (et vous devriez plutôt utiliser une liste générique). Il s'agit d'une collection d'éléments accessibles via un indexeur (par exemple [0]). Cela implique une progression d'un élément à l'autre.
Une liste liée spécifie une progression d'un élément à l'autre (élément a -> élément b). Vous pouvez obtenir le même effet avec une liste de tableaux, mais une liste liée indique absolument quel élément est censé suivre le précédent.
la source
Voir les Tutoriels Java - Liste des implémentations .
la source
Une caractéristique importante d'une liste chaînée (que je n'ai pas lue dans une autre réponse) est la concaténation de deux listes. Avec un tableau c'est O (n) (+ surcharge de certaines réallocations) avec une liste chaînée c'est seulement O (1) ou O (2) ;-)
Important : pour Java,
LinkedList
ce n'est pas vrai! Voir Existe - t-il une méthode de concaténation rapide pour la liste chaînée en Java?la source
next
d'une liste vers le premier nœud de la deuxième liste. La seule façon est d'utiliseraddAll()
qui ajoute des éléments de manière séquentielle, bien que ce soit mieux que de parcourir et d'appeleradd()
chaque élément. Pour ce faire rapidement dans O (1), vous auriez besoin d'une classe de composition (comme org.apache.commons.collections.collection.CompositeCollection), mais cela fonctionnerait pour tout type de liste / collection.ArrayList et LinkedList ont leurs propres avantages et inconvénients.
ArrayList utilise une adresse mémoire contiguë par rapport à LinkedList qui utilise des pointeurs vers le nœud suivant. Ainsi, lorsque vous souhaitez rechercher un élément dans une liste de tableaux est plus rapide que de faire n itérations avec LinkedList.
D'un autre côté, l'insertion et la suppression dans une LinkedList sont beaucoup plus faciles car il suffit de changer les pointeurs alors qu'une ArrayList implique l'utilisation d'une opération de décalage pour toute insertion ou suppression.
Si vous avez des opérations de récupération fréquentes dans votre application, utilisez une ArrayList. Si vous avez des insertions et des suppressions fréquentes, utilisez une LinkedList.
la source
J'ai lu les réponses, mais il y a un scénario où j'utilise toujours une LinkedList sur une ArrayList que je veux partager pour entendre des opinions:
Chaque fois que j'avais une méthode qui renvoie une liste de données obtenues à partir d'une base de données, j'utilise toujours une LinkedList.
Ma justification était que, comme il est impossible de savoir exactement combien de résultats j'obtiens, il n'y aura pas de perte de mémoire (comme dans ArrayList avec la différence entre la capacité et le nombre réel d'éléments), et il n'y aurait pas de temps perdu à essayer de dupliquer la capacité.
En ce qui concerne une ArrayList, je suis d'accord qu'au moins vous devriez toujours utiliser le constructeur avec la capacité initiale, afin de minimiser autant que possible la duplication des tableaux.
la source
ArrayList
etLinkedList
les outilsList interface
et leurs méthodes et résultats sont presque identiques. Cependant, il y a peu de différences entre elles qui se rendent meilleures les unes aux autres en fonction des besoins.ArrayList contre LinkedList
1) l'
Search:
ArrayList
opération de recherche est assez rapide par rapport à l'LinkedList
opération de recherche.get(int index)
inArrayList
donne les performances deO(1)
tandis que lesLinkedList
performances sontO(n)
.Reason:
ArrayList
maintient un système basé sur l'index pour ses éléments car il utilise implicitement la structure des données du tableau, ce qui le rend plus rapide pour rechercher un élément dans la liste. D'un autre côté,LinkedList
implémente une liste doublement liée qui nécessite la traversée de tous les éléments pour rechercher un élément.2) l'
Deletion:
LinkedList
opération de suppression donne desO(1)
performances tout enArrayList
offrant des performances variables:O(n)
dans le pire des cas (lors de la suppression du premier élément) etO(1)
dans le meilleur des cas (lors de la suppression du dernier élément).Raison: chaque élément de LinkedList conserve deux pointeurs (adresses) qui pointent vers les deux éléments voisins de la liste. Par conséquent, la suppression ne nécessite que la modification de l'emplacement du pointeur dans les deux nœuds voisins (éléments) du nœud qui va être supprimé. Dans In ArrayList, tous les éléments doivent être décalés pour remplir l'espace créé par l'élément supprimé.
3) la
Inserts Performance:
LinkedList
méthode add donne desO(1)
performances tandis queArrayList
donneO(n)
dans le pire des cas. La raison est la même que celle expliquée pour la suppression.4)
Memory Overhead:
ArrayList
gère les index et les données des éléments tout enLinkedList
conservant les données des éléments et deux pointeurs pour les nœuds voisinsIl existe peu de similitudes entre ces classes, à savoir:
iterator
etlistIterator
retournés par ces classes sontfail-fast
(si la liste est structurellement modifiée à tout moment après la création de l'itérateur, de quelque manière que ce soit, sauf par le biais desiterator’s
méthodes propres à supprimer ou ajouter, l'itérateur:throw
aConcurrentModificationException
).Quand utiliser LinkedList et quand utiliser ArrayList?
(O(1))
parLinkedList
rapport àArrayList(O(n))
.get method
opérations de recherche ( ) sont rapidesArraylist (O(1))
mais pasLinkedList (O(n))
la source
L'opération get (i) dans ArrayList est plus rapide que LinkedList, car:
ArrayList: implémentation de tableau redimensionnable de l'interface List
LinkedList: implémentation de liste à double liaison des interfaces List et Deque
Les opérations qui indexent dans la liste traverseront la liste depuis le début ou la fin, selon la valeur la plus proche de l'index spécifié.
la source
1) Structure de données sous-jacente
La première différence entre ArrayList et LinkedList vient du fait que ArrayList est soutenu par Array tandis que LinkedList est soutenu par LinkedList. Cela entraînera de nouvelles différences de performances.
2) LinkedList implémente Deque
Une autre différence entre ArrayList et LinkedList est qu'en dehors de l'interface List, LinkedList implémente également l'interface Deque, qui fournit des opérations de premier entré, premier sorti pour add () et poll () et plusieurs autres fonctions Deque. 3) Ajouter des éléments dans ArrayList Ajouter un élément dans ArrayList est une opération O (1) si elle ne déclenche pas la redimensionnement de Array, auquel cas il devient O (log (n)), En revanche, ajouter un élément dans LinkedList est une opération O (1), car elle ne nécessite aucune navigation.
4) Supprimer un élément d'une position
Afin de supprimer un élément d'un index particulier, par exemple en appelant remove (index), ArrayList effectue une opération de copie qui le rapproche de O (n) tandis que LinkedList doit traverser ce point qui le rend également O (n / 2) , car il peut traverser dans les deux sens en fonction de la proximité.
5) Itération sur ArrayList ou LinkedList
L'itération est l'opération O (n) pour LinkedList et ArrayList où n est un nombre d'un élément.
6) Récupération d'un élément d'une position
L'opération get (index) est O (1) dans ArrayList tandis que son O (n / 2) dans LinkedList, car elle doit traverser jusqu'à cette entrée. Cependant, en notation Big O, O (n / 2) est juste O (n) car nous ignorons les constantes.
7) Mémoire
LinkedList utilise un objet wrapper, Entry, qui est une classe imbriquée statique pour stocker les données et deux nœuds suivant et précédent tandis qu'ArrayList stocke simplement les données dans Array.
Les besoins en mémoire semblent donc moins importants dans le cas d'ArrayList que dans LinkedList, sauf dans le cas où Array effectue l'opération de redimensionnement lorsqu'il copie le contenu d'un tableau vers un autre.
Si Array est suffisamment grand, cela peut prendre beaucoup de mémoire à ce stade et déclencher le garbage collection, ce qui peut ralentir le temps de réponse.
De toutes les différences ci-dessus entre ArrayList et LinkedList, il semble qu'ArrayList soit le meilleur choix que LinkedList dans presque tous les cas, sauf lorsque vous effectuez une opération add () fréquente que remove () ou get ().
Il est plus facile de modifier une liste liée qu'ArrayList, surtout si vous ajoutez ou supprimez des éléments du début ou de la fin car la liste liée conserve en interne les références de ces positions et elles sont accessibles en temps O (1).
En d'autres termes, vous n'avez pas besoin de parcourir la liste liée pour atteindre la position où vous souhaitez ajouter des éléments, dans ce cas, l'addition devient une opération O (n). Par exemple, insérer ou supprimer un élément au milieu d'une liste liée.
À mon avis, utilisez ArrayList sur LinkedList pour la plupart des applications pratiques en Java.
la source
L'un des tests que j'ai vus ici ne fait le test qu'une seule fois. Mais ce que j'ai remarqué, c'est que vous devez exécuter ces tests plusieurs fois et, éventuellement, leurs temps convergeront. Fondamentalement, la JVM doit se réchauffer. Pour mon cas d'utilisation particulier, j'avais besoin d'ajouter / supprimer des éléments à une liste qui atteint environ 500 éléments. Lors de mes tests, je suis
LinkedList
sorti plus vite, avecLinkedList
environ 50 000 NS etArrayList
environ 90 000 NS ... à donner ou à prendre. Voir le code ci-dessous.la source
Remove () et insert () ont une efficacité d'exécution de O (n) à la fois pour ArrayLists et LinkedLists. Cependant, la raison du temps de traitement linéaire vient de deux raisons très différentes:
Dans une ArrayList, vous accédez à l'élément dans O (1), mais en réalité, la suppression ou l'insertion de quelque chose le rend O (n) car tous les éléments suivants doivent être modifiés.
Dans une LinkedList, il faut O (n) pour atteindre réellement l'élément souhaité, car nous devons commencer au tout début jusqu'à ce que nous atteignions l'index souhaité. En fait, la suppression ou l'insertion est constante, car il suffit de modifier 1 référence pour remove () et 2 références pour insert ().
Lequel des deux est plus rapide pour l'insertion et le retrait dépend de l'endroit où cela se produit. Si nous sommes plus proches du début, la LinkedList sera plus rapide, car nous devons passer par relativement peu d'éléments. Si nous sommes plus près de la fin, une ArrayList sera plus rapide, car nous y arriverons en temps constant et n'aurons qu'à changer les quelques éléments restants qui la suivent. Lorsqu'elle est effectuée précisément au milieu, la LinkedList sera plus rapide car parcourir n éléments est plus rapide que déplacer n valeurs.
Bonus: Bien qu'il n'y ait aucun moyen de rendre ces deux méthodes O (1) pour une ArrayList, il existe en fait un moyen de le faire dans LinkedLists. Disons que nous voulons parcourir toute la liste en supprimant et en insérant des éléments sur notre chemin. Habituellement, vous commenceriez depuis le tout début pour chaque élément en utilisant la LinkedList, nous pourrions également «enregistrer» l'élément actuel sur lequel nous travaillons avec un itérateur. Avec l'aide de l'itérateur, nous obtenons une efficacité O (1) pour remove () et insert () lorsque vous travaillez dans une LinkedList. Ce qui en fait le seul avantage en termes de performances, je sais où une LinkedList est toujours meilleure qu'une ArrayList.
la source
ArrayList étend AbstractList et implémente l'interface de liste. ArrayList est un tableau dynamique.
On peut dire qu'elle a été essentiellement créée pour surmonter les inconvénients des tableaux.
La classe LinkedList étend AbstractSequentialList et implémente l'interface List, Deque et Queue.
La performance
arraylist.get()
est O (1) alors quelinkedlist.get()
est O (n)arraylist.add()
est O (1) etlinkedlist.add()
est 0 (1)arraylist.contains()
est O (n) etlinkedlist.contains()
est O (n)arraylist.next()
est O (1) etlinkedlist.next()
est O (1)arraylist.remove()
est O (n) alors quelinkedlist.remove()
O (1)dans arraylist
iterator.remove()
est O (n)tandis que dans LinkedList
iterator.remove()
est O (1)la source