2009-04-04 7 views
4

Question rapide ici: pourquoi ne pas toujours utiliser ArrayLists en Java? Ils ont apparemment la même vitesse d'accès que les tableaux, en plus de fonctionnalités supplémentaires utiles. Je comprends la limitation en ce qu'il ne peut pas contenir des primitives, mais cela est facilement atténué par l'utilisation de wrappers.Pourquoi ne pas toujours utiliser ArrayLists en Java, au lieu de simples ol 'arrays?

+2

Voir http://stackoverflow.com/questions/716597/array-or-list-in-java-which-is-faster pour un fil raisonnable de discussion sur la question. – euphoria83

Répondre

5

Si vous avez besoin d'une collection de primitives, alors un tableau peut être le meilleur outil pour le travail. La boxe est une opération relativement coûteuse. Pour une collection (sans les cartes) de primitives qui seront utilisées comme primitives, j'utilise presque toujours un tableau pour éviter les répétitions de boxe et de déballage.

Cependant, je m'inquiète rarement de la différence de performance entre un tableau et un ArrayList. Si un List fournira un code meilleur, plus propre et plus maintenable, alors j'utiliserai toujours un List (ou Collection ou Set, etc., selon le cas, mais votre question portait sur ArrayList) à moins qu'il y ait une raison impérieuse de ne pas le faire. La performance est rarement cette raison impérieuse.

En utilisant Collection s presque toujours traduit par une meilleure code, en partie parce que les tableaux ne jouent pas bien avec les génériques, comme Johannes Weiß déjà fait remarquer dans un commentaire, mais aussi à cause de tant d'autres raisons:

  • Les collections ont une API très riche et une grande variété d'implémentations qui peuvent (dans la plupart des cas) être échangées entre elles
  • Une collection peut être trivialement convertie en tableau, si occasionnel utilisation d'un tableau la version est utile
  • De nombreuses collections se développent avec plus de grâce qu'un tableau se développe, ce qui peut être un problème de performances
  • Collections fonctionnent très bien avec les génériques, les tableaux assez mal
  • Comme TofuBeer a souligné, covariance de tableau est étrange et peut agir de manière unexected que pas l'objet va agir. Les collections gèrent la covariance de manière attendue.
  • Les tableaux doivent être dimensionnés manuellement pour leur tâche, et si un tableau n'est pas plein, vous devez en faire le suivi vous-même. Si un tableau doit être redimensionné, vous devez le faire vous-même.

Tout cela ensemble, j'utilise rarement des tableaux et utilise seulement un peu plus souvent un ArrayList. Cependant, j'utilise très souvent List s (ou seulement Collection ou Set). Mon utilisation la plus fréquente de tableaux est lorsque l'élément stocké est une primitive et sera inséré et accédé et utilisé comme une primitive. Si la boxe et le déballage deviennent si rapides que cela devient une considération triviale, je peux revenir sur cette décision, mais il est plus pratique de travailler avec quelque chose, de le stocker, sous la forme dans laquelle il est toujours référencé. (C'est-à-dire 'int' au lieu de 'Integer'.)

10

Beaucoup de projets utilisent simplement ArrayList ou HashMap ou autre pour gérer tous leurs besoins de collecte. Cependant, permettez-moi de mettre une mise en garde à ce sujet. Chaque fois que vous créez des classes et que vous les utilisez dans votre code, si possible, référez-vous aux interfaces qu'ils implémentent plutôt qu'aux classes concrètes que vous utilisez pour les implémenter.

Par exemple, plutôt que ceci:

ArrayList insuranceClaims = new ArrayList(); 

faire ceci:

List insuranceClaims = new ArrayList(); 

ou même:

Collection insuranceClaims = new ArrayList(); 

Si le reste de votre code, il ne connaît que par l'interface il implémente (List ou Collection) puis l'échange pour une autre implémentation mentation devient beaucoup plus facile sur la route si vous trouvez que vous en avez besoin d'un autre. J'ai vu cela se produire il ya juste un mois quand j'ai dû échanger un HashMap régulier pour une implémentation qui me renvoyait les éléments dans le même ordre que je les ai mis quand il était temps de les parcourir tous. Heureusement, une telle chose était disponible dans les collections communes de Jakarta et j'ai juste échangé A pour B avec seulement un changement de code d'une ligne parce que les deux ont mis en place la carte.

2

Eh bien, n'utilisez pas toujours aveuglément quelque chose qui ne convient pas au travail. Commencez toujours par utiliser les listes, choisissez ArrayList comme implémentation. C'est une approche plus OO. Si vous ne savez pas que vous avez spécifiquement besoin d'un tableau, vous constaterez que ne pas vous attacher à une implémentation particulière de List sera beaucoup mieux pour vous à long terme. Commencez par travailler, optimisez plus tard.

+0

La dernière partie, le faire fonctionner d'abord, optimiser plus tard, s'applique également aux tableaux ... – TofuBeer

+0

Absolument, appliquez-le à toute la programmation, algo ainsi qu'au stockage. Dans la plupart des cas, cette approche fonctionne bien. – wentbackward

4

Ceci est un cas de non-optimisation prématurée :-). Vous ne devriez jamais faire quelque chose parce que vous pensez que ce sera meilleur/plus rapide/vous rendre plus heureux. ArrayList a un surcoût supplémentaire, si vous n'avez pas besoin des fonctionnalités supplémentaires de ArrayList, il est inutile d'utiliser un ArrayList. En outre, pour certaines des choses que vous pouvez faire avec une liste, il y a la classe Arrays, ce qui signifie que ArrayList a fourni plus de fonctionnalités que Arrays est moins vrai. Maintenant, en utilisant ceux-ci pourrait être plus lent que d'utiliser un ArrayList, mais il devrait être profilé pour être sûr. Vous ne devriez jamais essayer de faire quelque chose de plus rapide sans être sûr qu'il est lent au début ... ce qui impliquerait que vous devriez aller de l'avant et utiliser ArrayList jusqu'à ce que vous découvriez qu'ils sont un problème et ralentissez le programme . Cependant, il devrait y avoir du bon sens aussi - ArrayList a des frais généraux, les frais généraux seront petits mais cumulatifs. Il ne sera pas facile de repérer un profileur, car tout ce qu'il y a ici, c'est un peu de frais généraux et un peu de frais généraux. Donc, le bon sens dirait, sauf si vous avez besoin des fonctionnalités de ArrayList vous ne devriez pas en faire usage, sauf si vous voulez mourir par des milliers de coupures (performance sage). Pour le code interne, si vous trouvez que vous avez besoin de passer de tableaux à ArrayList, la chance est assez simple dans la plupart des cas ([i] devient get (i), ce sera 99% des changements).

Si vous utilisez le look for-each (pour (value: items) {}) alors il n'y a pas de code à changer pour cela aussi.

En outre, aller avec ce que vous avez dit:

1) la vitesse d'égalité d'accès, en fonction de votre environnement. Par exemple, la machine virtuelle Android n'inline pas les méthodes (c'est juste un interprète droit autant que je sache) donc l'accès sur ce sera beaucoup plus lent. Il y a d'autres opérations sur ArrayList qui peuvent provoquer des ralentissements, cela dépend de ce que vous faites, quelle que soit la VM (qui pourrait être plus rapide avec un tableau stright, encore une fois vous devrez profiler ou examiner la source pour être sûr).

2) Les enveloppes augmentent la quantité de mémoire utilisée. Vous ne devriez pas vous soucier de la vitesse/mémoire avant de profiler quelque chose, d'un autre côté, vous ne devriez pas choisir ce que vous savez être une option plus lente, sauf si vous avez une bonne raison de le faire.

+0

Bien que je sois d'accord, et +1, je pense que votre réponse est trop verbeuse et trop large. :(Juste sayin '... –

+0

ouais, je l'ai répondu après avoir lu les autres messages ... donc j'essayais d'adresser beaucoup à la fois :-) – TofuBeer

4

Les performances ne devraient pas être votre principale préoccupation.

Utiliser l'interface List si possible, choisir l'implémentation concrète en fonction des besoins réels (ArrayList pour l'accès aléatoire, LinkedList pour les modifications structurelles, ...).

Vous devriez être préoccupé par les performances. Utilisez les tableaux, System.arraycopy, java.util.Arrays et d'autres éléments de bas niveau pour éliminer toute dernière goutte de performance.

Questions connexes