web-dev-qa-db-fra.com

Pourquoi ArrayDeque est-il meilleur que LinkedList?

J'essaie de comprendre pourquoi ArrayDeque de Java est meilleur que LinkedList de Java car ils implémentent tous les deux l'interface Deque.

Je vois à peine quelqu'un utiliser ArrayDeque dans son code. Si quelqu'un apporte plus de détails sur la manière dont ArrayDeque est implémenté, cela serait utile.

Si je le comprends, je serai plus confiant de l'utiliser. Je ne comprenais pas clairement la mise en œuvre du JDK en ce qui concerne la gestion des références tête et queue.

137
Cruel

Les structures liées sont probablement la pire structure à itérer avec un cache manquant sur chaque élément. En plus, ils consomment beaucoup plus de mémoire.

Si vous avez besoin d'ajouter/de supprimer les deux extrémités, ArrayDeque est nettement préférable à une liste chaînée. Accès aléatoire chaque élément est également O(1) pour une file d'attente cyclique.

Le seul fonctionnement optimal d'une liste chaînée consiste à supprimer l'élément actuel lors de l'itération.

134
bestsss

Je crois que le principal goulot d'étranglement des performances dans LinkedList est le fait que chaque fois que vous appuyez à une extrémité du décalage, l'implémentation alloue en arrière-plan un nouveau nœud de liste liée, qui implique essentiellement JVM/OS, et qui est coûteux. . De plus, chaque fois que vous sautez d'une extrémité à l'autre, les nœuds internes de LinkedList deviennent éligibles pour la récupération de place, ce qui représente davantage de travail en arrière-plan. De plus, étant donné que les nœuds de liste liés sont alloués ici et là, l'utilisation du cache du processeur n'apportera pas beaucoup d'avantages.

Si cela peut vous intéresser, j’ai la preuve que l’ajout d’un élément à ArrayList ou ArrayDeque s’exécute avec un temps constant amorti; se référer à this .

47
coderodde

ArrayDeque est nouveau avec Java 6, raison pour laquelle beaucoup de code (en particulier les projets essayant d'être compatibles avec les versions antérieures Java)) ne l'utilisez pas.

C'est "meilleur" dans certains cas, car vous n'attribuez pas de nœud à chaque élément à insérer; à la place, tous les éléments sont stockés dans un tableau géant, qui est redimensionné s'il est plein.

25

Toutes les personnes critiquant un LinkedList pensent à tous les autres gars qui ont utilisé List dans Java utilise probablement ArrayList et un LinkedList la plupart du temps parce qu'ils l'ont déjà été Java 6) et que ce sont ceux-ci qui sont enseignés dans la plupart des livres.

Mais cela ne veut pas dire que je prendrais aveuglément le côté de LinkedList ou de ArrayDeque. Si vous voulez savoir, jetez un coup d'œil au repère ci-dessous réalisé par Brian .

La configuration de test prend en compte:

  • Chaque objet de test est une chaîne de 500 caractères. Chaque chaîne est un objet différent en mémoire.
  • La taille de la matrice de test variera au cours des tests.
  • Pour chaque combinaison taille du tableau/mise en œuvre de la file d'attente, 100 tests sont exécutés et le temps moyen par test est calculé.
  • Chaque test consiste à remplir chaque file d'attente avec tous les objets, puis à les supprimer tous.
  • Mesurer le temps en millisecondes.

Résultat du test:

  • En dessous de 10 000 éléments, la moyenne des tests LinkedList et ArrayDeque est inférieure à 1 ms.
  • Au fur et à mesure que les ensembles de données deviennent plus grands, les différences entre les durées de test moyennes ArrayDeque et LinkedList deviennent plus grandes.
  • À la taille de test de 9 900 000 éléments, l’approche LinkedList a pris environ 165% plus longtemps que l’approche ArrayDeque.

Graphique:

enter image description here

À emporter:

  • Si votre exigence stocke 100 ou 200 éléments, utiliser l'une ou l'autre des files d'attente ne changera pas grand-chose.
  • Toutefois, si vous développez sur mobile, vous pouvez utiliser un ArrayList ou ArrayDeque avec une bonne estimation de la capacité maximale que la liste peut être requise en raison de contraintes de mémoire strictes.
  • Il y a beaucoup de code, écrit en utilisant un LinkedList, aussi soyez prudent lorsque vous décidez d'utiliser un ArrayDeque, car il NE met PAS en œuvre le List interface (je pense que c'est une raison assez grosse). Il se peut que votre base de code parle beaucoup à l’interface List et très probablement, et que vous décidiez d’intervenir avec un ArrayDeque. Son utilisation pour des implémentations internes pourrait être une bonne idée ...
10
pulp_fiction

Accéder à un élément dans ArrayDeque est toujours plus rapide que LinkedList avec O(1) pour accéder aux éléments. Dans une liste liée, il faudra O(N) trouver le dernier élément.

ArrayDeque est efficace en termes de mémoire car vous n'avez pas à suivre le noeud suivant contrairement à la liste liée.

Même selon la documentation de Java, il a été cité que

ArrayDeque est l'implémentation Resizable-array de l'interface Deque. Les tableaux de bord n'ont aucune limitation de capacité; ils se développent selon les besoins pour supporter l'utilisation. Ils ne sont pas thread-safe; en l'absence de synchronisation externe, ils ne prennent pas en charge l'accès simultané par plusieurs threads. Les éléments nuls sont interdits. Cette classe est probablement plus rapide que Stack lorsqu'elle est utilisée en tant que pile et plus rapide que LinkedList lorsqu'elle est utilisée en tant que file d'attente.

Benchmarking de ces deux prouve qu'ArrayDeque est plus rapide.

4
Ravindra babu

bien que ArrayDeque<E> et LinkedList<E> ont les deux implémentés Deque<E> Interface, mais ArrayDeque utilise essentiellement un tableau Object E[] pour conserver les éléments à l'intérieur de son objet, il utilise donc généralement index pour localiser les éléments head et tail.

Dans un mot, cela fonctionne comme Deque (avec la méthode de Deque), mais utilise la structure de données de array. En ce qui concerne lequel est le meilleur, dépend de comment et où vous les utilisez.

1
rekinyz