web-dev-qa-db-fra.com

ArrayDeque vs ArrayList pour implémenter une pile

La documentation de ArrayDeque dit:

Cette classe est susceptible d'être 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.

Il n'y a aucune mention de la différence entre l'utilisation d'un ArrayDeque comme pile et l'utilisation d'un ArrayList. Vous pouvez utiliser un ArrayList comme pile comme suit.

list.add(object);                      // Push
object = list.remove(list.size() - 1); // pop

J'ai constaté que lorsque j'utilisais un ArrayList de cette manière uniquement, ses performances étaient pires que ArrayDeque. Qu'est-ce qui explique cette différence? Sûrement, ce ne peut pas être juste les appels à size()? En interne, ArrayList et ArrayDeque sont implémentées à l'aide d'un Object[] Qui est remplacé par un tableau plus grand si nécessaire, donc les performances devraient être à peu près les mêmes?

27
Paul Boddington

La principale différence entre les deux implémentations est la stratégie de redimensionnement

  • ArrayList est redimensionné à une nouvelle taille de oldCapacity + (oldCapacity >> 1), résultant en une augmentation de ~ 50%. La capacité par défaut est 10, ce qui donne une capacité après redimensionnement de 15,22,33,49,73,109,163,244,366 ...

  • ArrayDeque est toujours redimensionné à une puissance de 2. Au redimensionnement, la capacité est doublée. À partir de la valeur par défaut de 16, les capacités de résolution après redimensionnement sont 32,64,128,256, ...

Ainsi, l'ArrayDeque atteint des capacités plus élevées avec une opération de redimensionnement beaucoup moins importante, ce qui est coûteux en raison de la copie de la matrice. C'est à dire. pour stocker 256 dans ArrayList de taille par défaut, il nécessite 9 appels de redimensionnement, tandis que ArrayDeque n'en a besoin que de 4. La copie de la matrice peut être rapide, mais peut également nécessiter un GC pour libérer de l'espace pour les nouveaux ensembles de données, en plus de la copie de la mémoire les coûts (où l'ArrayDeque pourrait également mieux fonctionner en raison de son alignement sur la puissance de 2).

Les deux infrastructures de données ont une complexité optimale de O(1) pour Push and pop via un accès direct sur head & tail (ArrayDequeue) respectivement ajouter et supprimer (Dernier) size (ArrayList)

18
Gerald Mücke