Interface de collecte vs tableaux

Nous apprenons à propos de l’interface de la collection et je me demandais si vous aviez tous de bons conseils pour son utilisation générale? Que pouvez-vous faire avec une collection que vous ne pouvez pas faire avec un tableau? Que pouvez-vous faire avec un tableau que vous ne pouvez pas faire avec une collection (en plus de permettre les doublons)?

C’est facile si vous pensez à cela comme suit: les collections sont meilleures que les tableaux d’objects, fondamentalement tous les moyens imaginables.

Vous devriez préférer List à Foo[] autant que possible. Considérer:

  • Une collection peut être mutable ou immuable. Un tableau non vide doit toujours être mutable.
  • Une collection peut être thread-safe; même concurrente Un tableau n’est jamais sûr à publier sur plusieurs threads.
  • Une collection peut autoriser ou interdire les éléments nuls. Un tableau doit toujours autoriser les éléments nuls.
  • Une collection est de type sécurisé; un tableau ne l’est pas. Parce que les tableaux “falsifient” la covariance, ArrayStoreException peut se produire lors de l’exécution.
  • Une collection peut contenir un type non-reifiable (par exemple, List> Extend List> ou List> ). Avec un tableau, vous obtenez des avertissements de compilation et des exceptions d’exécution confuses.
  • Une collection dispose d’une API entièrement développée. un tableau n’a que set-at-index, get-at-index et length.
  • Une collection peut avoir des vues (non modifiables, sous-liste, filtre …). Pas de chance pour un tableau.
  • Une liste ou un ensemble equals méthodes hashCode et toSsortingng . ces méthodes sur un tableau font tout sauf ce que vous attendez – une source commune de bogues.
  • Pour toutes les raisons citées ci-dessus, les bibliothèques tierces telles que Guava ne prendront pas la peine d’append beaucoup de support supplémentaire aux baies, en se concentrant uniquement sur les collections, ce qui crée un effet de réseau.

Les tableaux d’objects ne seront jamais des citoyens de première classe en Java.

Certaines des raisons ci-dessus sont traitées de manière beaucoup plus détaillée dans Effective Java, Second Edition , à partir de la page 119.

Alors, pourquoi utiliseriez-vous des tableaux d’objects?

  • Vous devez interagir avec une API qui les utilise et vous ne pouvez pas réparer cette API
    • convertissez donc vers / depuis une List aussi proche de cette API que possible
  • Vous avez un benchmark fiable qui montre que vous obtenez de meilleures performances avec eux
    • mais les repères peuvent se situer et souvent
  • Je ne peux penser à aucune autre raison

C’est essentiellement une question de niveau d’abstraction souhaité.

La plupart des collections peuvent être implémentées en termes de baies, mais elles fournissent beaucoup plus de méthodes par souci de commodité. La plupart des implémentations de collections que je connais, par exemple, peuvent croître et diminuer en fonction de la demande, ou effectuer d’autres opérations «de haut niveau», auxquelles les baies de base ne peuvent pas accéder.

Supposons par exemple que vous chargez des chaînes à partir d’un fichier. Vous ne savez pas combien de caractères de nouvelle ligne le fichier contient, vous ne savez donc pas quelle taille utiliser lors de l’allocation du tableau. Par conséquent, une ArrayList est un meilleur choix.

Les détails se trouvent dans les sous-interfaces de Collection, telles que Définir, Liste et Carte. Chacun de ces types a une sémantique . Un ensemble ne peut généralement pas contenir de doublons et n’a aucune notion d’ordre (bien que certaines implémentations le soient), suivant le concept mathématique d’un ensemble. Une liste est la plus proche d’un tableau. Une carte a un comportement spécifique pour pousser et obtenir. Vous poussez un object par sa clé et vous récupérez avec la même clé.

Il y a encore plus de détails dans les implémentations de chaque type de collection. Par exemple, les collections basées sur le hachage (par exemple, HashSet, HasMap) sont basées sur la méthode hashcode () qui existe sur tout object Java.

Vous pouvez simuler la sémantique de tout type de collection basé sur un tableau, mais vous devrez écrire beaucoup de code pour le faire. Par exemple, pour sauvegarder une carte avec un tableau, vous devez écrire une méthode qui place n’importe quel object entré dans votre map dans un compartiment spécifique du tableau. Vous devez gérer les doublons. Pour un tableau simulant un ensemble, vous devez écrire du code pour ne pas autoriser les doublons.

L’interface Collection est juste une interface de base pour les collections spécialisées – je ne suis pas encore au courant d’une classe qui implémente simplement Collection; à la place, les classes implémentent des interfaces spécialisées qui étendent Collection. Ces interfaces spécialisées et ces classes abstraites fournissent des fonctionnalités pour travailler avec des ensembles (objects uniques), des tableaux croissants (par exemple, ArrayList), des cartes de valeurs-clés, etc., que vous ne pouvez pas utiliser avec un tableau. Cependant, l’itération à travers un tableau et la définition / lecture d’éléments à partir d’un tableau restnt l’une des méthodes les plus rapides pour traiter les données en Java.

Un avantage est l’interface Iterator. C’est-à-dire que toutes les collections implémentent un iterator. Un iterator est un object qui sait itérer sur la collection donnée et présente au programmeur une interface uniforme quelle que soit l’implémentation sous-jacente. En d’autres termes, une liste chaînée est traversée différemment d’un arbre binary, mais l’iterator masque ces différences avec le programmeur, ce qui permet au programmeur d’utiliser plus facilement l’une ou l’autre collection.

Cela permet également d’utiliser plusieurs implémentations de collections de manière interchangeable si le code client cible l’interface de collection.