JavaRush /Blog Java /Random-FR /Les 10 principales questions sur les collections en Java
FedoraLinux
Niveau 21
Москва

Les 10 principales questions sur les collections en Java

Publié dans le groupe Random-FR
L'article est une traduction de l'article « Top 10 des questions sur les collections Java » . Vous trouverez ci-dessous les questions les plus courantes sur les collections en Java, posées et discutées sur Stackowerflow. Avant d’examiner ces questions, il serait bon d’examiner le diagramme hiérarchique des classes. 1. Quand utiliser LinkedList au lieu d’ArrayList ? Une ArrayList est en fait un tableau ; ses éléments sont accessibles directement par index. Si le tableau déborde, un nouveau avec plus d'espace devient nécessaire. Placer et déplacer tous les éléments prendra un temps O(n). De plus, l'ajout et la suppression d'éléments sont nécessaires pour déplacer les éléments existants dans le tableau. C'est peut-être le plus gros inconvénient de l'utilisation d'ArrayList. LinkedList est une double liste de liens d'éléments. Ainsi, pour accéder à l'élément du centre, il faut chercher du tout début à la fin de la feuille. En revanche, l'ajout et la suppression d'un élément dans une LinkedList sont plus rapides car ces opérations ne modifient que la liste elle-même. Les pires moments sont comparés ci-dessous :
Méthode Liste des tableaux Liste liée
obtenir (index) O(1) Sur)
ajouter(E) Sur) O(1)
ajouter (E, index) Sur) Sur)
supprimer (index) Sur) Sur)
Itérateur.remove() Sur) O(1)
Itérateur.add(E) Sur) O(1)
Malgré le temps d'exécution, l'utilisation de la mémoire doit être considérée individuellement pour les grandes listes. Dans une LinkedList, chaque nœud doit avoir au moins deux pointeurs supplémentaires pour relier les nœuds précédent et suivant, tandis que dans une ArrayList, seul un tableau d'éléments est nécessaire. Plus de comparaisons des listes ArrayList, LinkedList et Vector . 2. Equivalent efficace pour supprimer des éléments lors de l'itération d'une collection La seule façon correcte de modifier (supprimer des éléments) une collection pendant l'itération est d'utiliser Iterator.remove() . Par exemple : L'erreur la plus courante est : Vous obtiendrez une ConcurrentModificationException lors de l'exécution du code ci-dessus. Cela se produit parce que l'itérateur a été généré pour parcourir toute la liste, mais en même temps la feuille est modifiée en appelant Iterator.remove(). Comme écrit dans la documentation de cette exception, Iterator itr = list.iterator(); while(itr.hasNext()) { // do something itr.remove(); } for(Integer i: list) { list.remove(i); }
"il n'est généralement pas permis à un thread de modifier une collection pendant qu'un autre thread la parcourt."
En général, il est inacceptable qu'un thread modifie une collection pendant qu'un autre thread la parcourt. 3. Comment convertir une liste en tableau int[] ? Le moyen le plus simple de procéder consiste à utiliser ArrayUtils , situé dans la bibliothèque Apache Commons Lang . int[] array = ArrayUtils.toPrimitive(list.toArray(new Integer[0])); Il n'existe aucun raccourci pour cette expression dans le JDK. N'oubliez pas que vous ne pouvez pas utiliser List.toArray() car cette expression convertit List en Integer[] (qui n'est pas un type primitif). La méthode correcte serait l'option suivante : int[] array = new int[list.size()]; for(int i=0; i < list.size(); i++) { array[i] = list.get(i); } 4. Comment convertir un tableau int[] en liste ? Le moyen le plus simple est également d'utiliser ArrayUtils dans la bibliothèque Apache Commons Lang , comme ci-dessus. List list = Arrays.asList(ArrayUtils.toObject(array)); De plus, il n'existe aucun raccourci pour cette expression dans le JDK. 5. Quelle est la meilleure façon de filtrer la collection ? Vous pouvez utiliser des packages tiers tels que Guava ou Apache Commons Lang pour augmenter les fonctionnalités. Ces deux packages ont une méthode filter() (dans la classe Collections2 de Guava et CollectionUtils d'Apache). La méthode filter() renverra les éléments qui correspondent au prédicat donné. Dans JDK, tout est plus compliqué. La bonne nouvelle est que des prédicats seront ajoutés dans Java 8 , mais pour l'instant, vous devez utiliser Iterator pour parcourir toute la collection. Bien entendu, vous pouvez imiter le chemin suivi par Guava et Apache en vous familiarisant avec la nouvelle interface Predicate. Nous pouvons maintenant utiliser le code suivant pour filtrer la collection : 6. Comment convertir facilement List en Set ? Il existe deux manières de procéder, selon la façon dont vous souhaitez définir l’égalité. Le premier morceau de code place la liste dans un HashSet. Le doublon dans ce cas est déterminé principalement par hashCode(). Généralement, cela fonctionnera. Mais si vous devez prendre en compte le chemin de comparaison, alors il serait préférable d'utiliser la deuxième partie du code, où vous pourrez définir votre propre comparateur. 7. Comment puis-je supprimer les éléments en double d'une ArrayList ? Cette question est quelque peu liée à la question ci-dessus. Si l'ordre des éléments dans ArrayList n'a pas d'importance pour vous, une solution intelligente serait de placer la feuille dans un ensemble pour supprimer les doublons, puis de la remettre dans la liste. Ci-dessous un exemple. Si l'ordre des éléments vous intéresse, l'ordre peut être assuré en plaçant la liste dans un LinkedHashSet , qui se trouve dans le JDK standard. 8. Collection triée int[] array = {1,2,3,4,5}; List list = new ArrayList (); for(int i: array) { list.add(i); } Iterator itr = list.iterator(); while(itr.hasNext()) { int i = itr.next(); if (i > 5) { // filter all ints bigger than 5 itr.remove(); } } public interface Predicate { boolean test(T o); } public static void filter(Collection collection, Predicate predicate) { if ((collection != null) && (predicate != null)) { Iterator itr = collection.iterator(); while(itr.hasNext()) { T obj = itr.next(); if (!predicate.test(obj)) { itr.remove(); } } } } filter(list, new Predicate () { public boolean test(Integer i) { return i <= 5; } }); Set set = new HashSet (list); Set set = new TreeSet (aComparator); set.addAll(list); ArrayList** list = ... // initial a list with duplicate elements Set set = new HashSet (list); list.clear(); list.addAll(set); Il existe plusieurs façons de prendre en charge une collection triée en Java. Tous fournissent une collection dans l'ordre naturel ou par un comparateur spécifié. Dans le cas d'un ordre naturel, vous devez également implémenter l' interface Comparable sur l'élément.
  1. Collections.sort() peut trier une liste. Comme indiqué dans la documentation Java, ce tri est stable et garantit des performances n log(n).
  2. PriorityQueue fournit une file d'attente ordonnée. La différence entre PriorityQueue et Collections.sort() est que PriorityQueue maintient l'ordre de la file d'attente à tout moment, mais vous ne pouvez obtenir que le premier élément de la file d'attente. Vous ne pouvez pas accéder au hasard à un élément comme PriorityQueue.get(4).
  3. S'il n'y a pas de doublons dans la collection, vous pouvez sélectionner TreeSet . Tout comme PriorityQueue, TreeSet maintient un ensemble ordonné à tout moment. Vous pouvez obtenir le plus petit ou le plus grand élément d’un TreeSet, mais vous ne pouvez toujours pas avoir un accès aléatoire aux éléments.
En termes simples, Collections.sort() fournit une liste ordonnée unique. PriorityQueue et TreeSet maintiennent une collection ordonnée à tout moment, au prix du manque d'accès indexé aux éléments. 9. Collections.emptyList() ou nouvelle instance La même question s'applique à emptyMap() et emptySet(). Les deux méthodes renvoient une liste vide, mais Collections.emptyList() est une liste immuable. Cela signifie que vous ne pouvez pas ajouter de nouveaux éléments à une liste « vide ». En arrière-plan, chaque appel à la méthode Collections.emptyList() ne crée pas réellement une nouvelle instance de la liste vide. Au lieu de cela, il réutilisera l'instance vide déjà existante. Si vous connaissez Singleton en tant que modèle de conception , vous devez comprendre ce que cela signifie. Cela devrait vous donner de meilleures performances si vous êtes appelé fréquemment. 10 Copie d'une collection, Collections.copy() Il existe deux manières de copier une liste source vers une liste de destination. Une solution consiste à utiliser le constructeur ArrayList. Une autre façon consiste à utiliser la méthode Collections.copy() . Remarquez sur la première ligne : nous allouons une liste qui a au moins la même longueur que la longueur de la liste d'origine, car la documentation Java sur les collections dit : ArrayList dstList = new ArrayList (srcList);
La liste de destination doit être au moins aussi longue que la liste source.
Cela signifie que la liste finale ne doit pas être plus courte que la liste originale. Les deux méthodes sont une copie superficielle. Alors, quelle est la différence entre ces deux méthodes ? Premièrement, Collections.copy() ne réaffectera pas la capacité de la collection dstList, même si la dstList ne dispose pas de suffisamment d'espace pour contenir tous les éléments de la srcList. Au lieu de cela, il lancera IndexOutOfBoundsException . On pourrait se demander si cela présente un avantage. La raison en est que cela garantit que la méthode s’exécute de manière linéaire dans le temps. Cela convient également lorsque vous souhaitez réutiliser des tableaux plutôt que de réallouer de la mémoire dans le constructeur ArrayList. Au lieu d'une conclusion Si après avoir lu l'article vous avez encore des questions, n'hésitez pas à les poser dans les commentaires. Aussi, si vous constatez une inexactitude dans la traduction ou toute autre erreur, alors écrivez au MP, cela sera corrigé et vous serez remercié. Original. ArrayList dstList = new ArrayList (srcList.size()); Collections.copy(dstList, srcList);
Commentaires
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION