En lisant la documentation Java pour la liste ADT, il est dit:
L'interface Liste fournit quatre méthodes d'accès positionnel (indexé) aux éléments de liste. Les listes (comme les tableaux Java) sont basées sur zéro. Notez que ces opérations peuvent s'exécuter en temps proportionnel à la valeur d'index pour certaines implémentations (la classe LinkedList, par exemple). Ainsi, l'itération sur les éléments d'une liste est généralement préférable à l'indexation à travers celle-ci si l'appelant ne connaît pas l'implémentation.
Qu'est-ce que cela veut dire exactement? Je ne comprends pas la conclusion qui est tirée.
Réponses:
Dans une liste liée, chaque élément a un pointeur vers l'élément suivant:
Pour y accéder
item3
, vous pouvez voir clairement que vous devez marcher de la tête à travers chaque nœud jusqu'à ce que vous atteigniez l'élément 3, car vous ne pouvez pas sauter directement.Ainsi, si je voulais imprimer la valeur de chaque élément, si j'écris ceci:
ce qui se passe est ceci:
C'est horriblement inefficace car chaque fois que vous indexez, il redémarre depuis le début de la liste et parcourt chaque élément. Cela signifie que votre complexité est effectivement
O(N^2)
juste de parcourir la liste!Si à la place je faisais ceci:
alors ce qui se passe est ceci:
le tout en un seul parcours, qui est
O(N)
.Maintenant, passons à l'autre implémentation
List
dontArrayList
celle-ci est soutenue par un simple tableau. Dans ce cas, les deux parcours ci-dessus sont équivalents, puisqu'un tableau est contigu, il permet donc des sauts aléatoires vers des positions arbitraires.la source
REVERSE_THRESHOLD
est défini à 18java.util.Collections
po, il est étrange de voir une réponse aussi positive sans la remarque.List l = unknownList(); if (l instanceof RandomAccess) /* do indexed loop */ else /* use iterator/foreach */
La réponse est implicite ici:
Une liste chaînée n'a pas d'index inhérent; l'appel
.get(x)
nécessitera que l'implémentation de la liste trouve la première entrée et appelle.next()
x-1 fois (pour un accès en temps O (n) ou linéaire), où une liste basée sur un tableau peut simplement indexer enbackingarray[x]
O (1) ou en temps constant.Si vous regardez le JavaDoc pour
LinkedList
, vous verrez le commentairealors que JavaDoc pour
ArrayList
a le correspondantUne question associée intitulée "Big-O Summary for Java Collections Framework" a une réponse pointant vers cette ressource, "Java Collections JDK6", qui pourrait vous être utile.
la source
Bien que la réponse acceptée soit très certainement correcte, pourrais-je signaler un défaut mineur. Citant Tudor:
Ce n'est pas tout à fait vrai. La vérité c'est que
source: Designing for Performance, document Android de Google
Notez que la boucle manuscrite fait référence à l'itération indexée. Je soupçonne que c'est à cause de l'itérateur qui est utilisé avec des boucles for améliorées. Il produit une performance mineure en pénalité dans une structure qui est soutenue par un tableau contigu. Je soupçonne également que cela pourrait être vrai pour la classe Vector.
Ma règle est la suivante: utilisez la boucle for améliorée chaque fois que possible, et si vous vous souciez vraiment des performances, utilisez l'itération indexée uniquement pour ArrayLists ou Vectors. Dans la plupart des cas, vous pouvez même l'ignorer - le compilateur optimise peut-être cela en arrière-plan.
Je tiens simplement à souligner que dans le contexte du développement sous Android, les deux parcours des ArrayLists ne sont pas forcément équivalents . Juste matière à réflexion.
la source
Itérer sur une liste avec un décalage pour la recherche, comme
i
, est analogue à l'algorithme de Shlemiel le peintre .Source .
Cette petite histoire peut permettre de comprendre plus facilement ce qui se passe en interne et pourquoi c'est si inefficace.
la source
Pour trouver le i-ème élément d'un,
LinkedList
l'implémentation passe par tous les éléments jusqu'au i-ème.Alors
la source