Quelle collection Java dois-je utiliser?


127

Dans cette question Comment puis-je sélectionner efficacement un conteneur de bibliothèque standard dans C ++ 11? est un organigramme pratique à utiliser lors du choix des collections C ++.

J'ai pensé que c'était une ressource utile pour les personnes qui ne savaient pas quelle collection ils devraient utiliser, j'ai donc essayé de trouver un organigramme similaire pour Java et je n'ai pas pu le faire.

Quelles ressources et «aide-mémoire» sont disponibles pour aider les gens à choisir la bonne collection à utiliser lors de la programmation en Java? Comment les gens savent-ils quelles implémentations List, Set et Map ils doivent utiliser?


Le livre Java Generics and Collections (Naftalin & Wadler) contient un chapitre à ce sujet.
Christophe Roussy

Réponses:


293

Comme je n'ai pas trouvé d'organigramme similaire, j'ai décidé d'en créer un moi-même.

Cet organigramme n'essaie pas de couvrir des choses comme l'accès synchronisé, la sécurité des threads, etc. ou les collections héritées, mais il couvre les 3 ensembles standard , 3 cartes standard et 2 listes standard .

entrez la description de l'image ici

Cette image a été créée pour cette réponse et est sous licence Creative Commons Attribution 4.0 International License. L'attribution la plus simple consiste à établir un lien vers cette question ou cette réponse.

Autres ressources

L'autre référence probablement la plus utile est la page suivante de la documentation oracle qui décrit chaque collection .

HashSet vs TreeSet

Il y a une discussion détaillée sur quand utiliser HashSetou TreeSetici: Hashset vs Treeset

ArrayList vs LinkedList

Discussion détaillée: Quand utiliser LinkedList sur ArrayList?


Agréable! Mais je dois être en désaccord avec vos décisions LinkedListvs. ArrayListPremièrement, si la liste est de taille significative, LinkedListc'est préférable. LinkedLista une surcharge par élément, il est donc asymptotiquement pire en termes de consommation de mémoire qu'un ArrayList. De plus, si la plupart des accès se trouvent à la fin de la liste, un ArrayListest préférable car il fournit un accès aléatoire aux éléments en temps constant. Accéder au ne élément de a LinkedListest une O(n)opération. ... En fait, la décision d'utiliser une liste chaînée devrait presque toujours être "non".
Matt Ball

2
@MattBall Je suis d'accord avec vous pour la plupart. Cependant Java LinkedListest une double liste chaînée, donc l'accès au début et à la fin sont tous deux rapides. Vous noterez que parmi les branches ci-dessus, les trois questions doivent répondre oui avant de recommander l'utilisation de LinkedList- donc en d'autres termes, je suis d'accord avec vous que dans la plupart des cas, la réponse est non. Des choses comme les files d'attente et les retraits de file d'attente où vous ajoutez et supprimez constamment des éléments aux extrémités de la zone de liste sont un bon cas d'utilisation LinkedList.
Tim B

@MattBall L'utilisation de la mémoire est une situation beaucoup plus délicate, car si a LinkedListutilise plus de mémoire par élément ... ArrayListne libère jamais de mémoire. Cela signifie que si vous avez une liste qui atteint parfois une taille énorme mais qui est généralement petite, alors ArrayListles performances de la mémoire seront moins bonnes. La surcharge de mémoire de Listlui-même est généralement (mais pas toujours) faible par rapport à celle des éléments qu'il contient également.
Tim B

Map<K,V>n'est pas la partie dejava.util.collection
Mehraj Malik

@MehrajMalik Hmm, l'étiquetage est ambigu, je suis d'accord. Je voulais dire Collection à l'intérieur de java.util. ie java.util. * insérer le nom de la collection ici *
Tim B

66

Résumé des principales collections non simultanées et non synchronisées

Collection: Une interface représentant un "sac" d'articles non ordonné, appelé "éléments". L'élément "suivant" n'est pas défini (aléatoire).

  • Set: Une interface représentant un Collectionsans doublon.
    • HashSet: Un Setsoutenu par un Hashtable. Utilisation de la mémoire la plus rapide et la plus petite, lorsque la commande n'a pas d'importance.
    • LinkedHashSet: A HashSetavec l'ajout d'une liste chaînée pour associer des éléments dans l' ordre d'insertion . L'élément "suivant" est l'élément inséré le plus récemment.
    • TreeSet: A Setoù les éléments sont ordonnés par un Comparator(typiquement ordre naturel ). Utilisation de la mémoire la plus lente et la plus importante, mais nécessaire pour la commande basée sur un comparateur.
    • EnumSet: Une personnalisation extrêmement rapide et efficace Setpour un seul type d'énumération.
  • List: Une interface représentant un Collectiondont les éléments sont ordonnés et ont chacun un index numérique représentant sa position, où zéro est le premier élément et (length - 1)le dernier.
    • ArrayList: A Listsoutenu par un tableau, où le tableau a une longueur (appelée «capacité») qui est au moins aussi grande que le nombre d'éléments (la «taille» de la liste). Lorsque la taille dépasse la capacité (lorsque l' (capacity + 1)-thélément est ajouté), le tableau est recréé avec une nouvelle capacité de - (new length * 1.5)cette récréation est rapide, car elle utilise System.arrayCopy(). La suppression et l'insertion / l'ajout d'éléments nécessitent que tous les éléments voisins (à droite) soient déplacés dans ou hors de cet espace. L'accès à n'importe quel élément est rapide, car il ne nécessite que le calcul (element-zero-address + desired-index * element-size)pour trouver son emplacement. Dans la plupart des situations , un ArrayListest préférable à un LinkedList.
    • LinkedList: A Listsoutenu par un ensemble d'objets, chacun lié à ses voisins "précédent" et "suivant". A LinkedListest également un Queueet Deque. L'accès aux éléments se fait en commençant au premier ou au dernier élément, et en parcourant jusqu'à ce que l'index souhaité soit atteint. L'insertion et la suppression, une fois que l'index souhaité est atteint par traversée, est une question triviale de remapper uniquement les liens voisins immédiats pour pointer vers le nouvel élément ou contourner l'élément maintenant supprimé.
  • Map: Une interface représentant un Collectionoù chaque élément a une "clé" d'identification - chaque élément est une paire clé-valeur.
    • HashMap: A Mapoù les clés ne sont pas ordonnées et sont soutenues par a Hashtable.
    • LinkedhashMap: Les clés sont classées par ordre d' insertion .
    • TreeMap: A Mapoù les clés sont ordonnées par un Comparator(typiquement ordre naturel).
  • Queue: Une interface qui représente un Collectionélément où les éléments sont généralement ajoutés à une extrémité et supprimés de l'autre (FIFO: premier entré, premier sorti).
  • Stack: Une interface qui représente un Collectionélément où les éléments sont, généralement, à la fois ajoutés (poussés) et supprimés (sautés) de la même extrémité (LIFO: dernier entré, premier sorti).
  • Deque: Abréviation de "file d'attente double", généralement prononcée "deck". Une liste liée qui est généralement ajoutée et lue à chaque extrémité (pas au milieu).

Diagrammes de collecte de base:

diagramme

Comparaison de l'insertion d'un élément avec un ArrayListet LinkedList:

diagramme


2
Le meilleur en bref estival qu'on peut aller n'importe où :)
roottraveller

11

Une image encore plus simple est ici. Intentionnellement simplifié!

  1. La collection est tout ce qui contient des données appelées «éléments» (du même type). Rien de plus spécifique n'est supposé.

  2. List est unecollection indexée de données où chaque élément a un index. Quelque chose comme le tableau, mais plus flexible.

    Les données de la liste conservent l'ordre d'insertion.

    Opération typique: obtenir le n-ième élément.

  3. L'ensemble est un sac d'éléments , chaque élément une seule fois (les éléments se distinguent par leurequals()méthode.

    Les données de l'ensemble sont stockées principalement pour savoir quelles sont les données présentes.

    Opération typique: dire si un élément est présent dans la liste.

  4. La carte est quelque chose comme la liste, mais au lieu d'accéder aux éléments par leur index entier, vous y accédez par leur clé , qui est n'importe quel objet. Comme le tableau en PHP :)

    Les données de la carte peuvent être recherchées par leur clé.

    Opéraion typique: obtenir un élément par son ID (où ID est de n'importe quel type, pas seulement intcomme dans le cas de List).

Les différences

  • Set and Map: dans Set vous recherchez les données par eux - mêmes , tandis que dans Map par leur clé .

  • List and Map: dans List vous accédez à l'élément par leur intindex (position dans List), tandis que dans Map par leur clé quel os de n'importe quel type (typiquement: ID)

  • List and Set: dans List les éléments sont liés par leur position et peuvent être dupliqués, tandis que dans Set les éléments sont juste "present" (pr not present) et sont uniques (au sens de equals(), ou compareTo()pour SortedSet)


1

C'est simple: si vous avez besoin de stocker des valeurs avec des clés qui y sont mappées, allez dans l'interface Map, sinon utilisez List pour les valeurs qui peuvent être dupliquées et utilisez enfin l'interface Set si vous ne voulez pas de valeurs dupliquées dans votre collection.

Voici l'explication complète http://javatutorial.net/choose-the-right-java-collection , y compris l'organigramme, etc.


1

Carte

Si vous choisissez a Map, j'ai fait ce tableau résumant les fonctionnalités de chacune des dix implémentations fournies avec Java 11.

Tableau des implémentations de carte dans Java 11, comparant leurs fonctionnalités



-2

Quelle collection Java dois-je utiliser?

Cela dépend du problème que vous essayez de résoudre ou des exigences que vous avez.

Exemples :

  1. Voulez-vous que les éléments soient triés lors de leur stockage? HashSet
  2. Voulez-vous que les paires (clé, valeur) soient stockées? HashMap
  3. Voulez-vous que l'ordre des éléments lors de leur insertion soit conservé? ArrayList, LinkedList
  4. Voulez-vous que les clés de la paire (clé, valeur) soient triées? - texte fort
  5. Voulez-vous implémenter une pile pour résoudre votre problème? - Pile
  6. Voulez-vous avoir un accès FIFO (premier entré, premier sorti)? - File d'attente
  7. Voulez-vous que seuls les éléments UNIQUE soient stockés? - HashSet
  8. Voulez-vous autoriser la clé comme "Null" lors du stockage (clé, valeur)? - HashMap
  9. Voulez-vous aucune valeur NULL pour la paire (clé, valeur)? HashTable

Même avec un texte fort au point 4 remplacé par, disons, ConcurrentSkipListMap (K, V) , qu'est-ce que cette réponse ajoute au graphe de décision de Tim B , aux "descriptions de liste restreinte " d'aliteralmind ?
greybeard

Votre premier point, HashSet ne trie pas les données, même l'ordre d'insertion n'est pas conservé. Vous devriez le changer avec TreeSet
Saurabh Mishra
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.