web-dev-qa-db-fra.com

Comment instancier un tableau de cartes en Java?

Je peux déclarer un tableau de cartes en utilisant des génériques pour spécifier le type de carte:

private Map<String, Integer>[] myMaps;

Cependant, je ne sais pas comment l'instancier correctement:

myMaps = new HashMap<String, Integer>[count]; // gives "generic array creation" error
myMaps = new HashMap[count]; // gives an "unchecked or unsafe operation" warning
myMaps = (Map<String, Integer>[])new HashMap[count]; // also gives warning

Comment puis-je instancier ce tableau de cartes sans obtenir d'erreur ou d'avertissement du compilateur?

Mise à jour:

Merci à tous pour vos réponses. J'ai fini par accepter la suggestion de liste.

34
Karl von L

Pas strictement une réponse à votre question, mais avez-vous envisagé d'utiliser un List à la place?

List<Map<String,Integer>> maps = new ArrayList<Map<String,Integer>>();
...
maps.add(new HashMap<String,Integer>());

semble fonctionner très bien.

Voir Théorie et pratique Java: gotchas génériques pour une explication détaillée des raisons pour lesquelles le mélange de tableaux avec des génériques est déconseillé.

Mise à jour:

Comme mentionné par Drew dans les commentaires, il pourrait être encore mieux d'utiliser l'interface Collection au lieu de List. Cela peut être utile si vous avez besoin de passer à un Set, ou à l'une des autres sous-interfaces de Collection. Exemple de code:

Collection<Map<String,Integer>> maps = new HashSet<Map<String,Integer>>();
...
maps.add(new HashMap<String,Integer>());

À partir de ce point de départ, il vous suffit de remplacer HashSet par ArrayList, PriorityQueue ou toute autre classe qui implémente Collection.

38
Bill the Lizard

Vous ne pouvez pas créer en toute sécurité un tableau générique. Efficace Java 2nd Edition va dans les détails dans le chapitre sur les génériques . Commencez par le dernier paragraphe de la page 119:

Pourquoi est-il illégal de créer un tableau générique? Parce que ce n'est pas sûr pour les types. S'il était légal, les conversions générées par le compilateur dans un programme par ailleurs correct pourraient échouer lors de l'exécution avec un ClassCastException. Cela violerait la garantie fondamentale fournie par le système de type générique.

Pour rendre cela plus concret, considérez le fragment de code suivant:

// Why generic array creation is illegal - won't compile!
List<String>[] stringLists = new List<String>[1]; // (1)
List<Integer> intList = Arrays.asList(42); // (2)
Object[] objects = stringLists; // (3)
objects[0] = intList; // (4)
String s = stringLists[0].get(0); // (5)

Imaginons que la ligne 1, qui crée un tableau générique, est légale. La ligne 2 crée et initialise un List<Integer> contenant un seul élément. La ligne 3 stocke le List<String> array dans une variable de tableau Object, ce qui est légal car les tableaux sont covariants. La ligne 4 stocke le List<Integer> dans le seul élément du tableau Object, qui réussit car les génériques sont implémentés par effacement: le type d'exécution d'un List<Integer> instance est simplement List, et le type d'exécution d'un List<String>[] l'instance est List[], donc cette affectation ne génère pas de ArrayStoreException. Maintenant, nous avons des ennuis. Nous avons stocké un List<Integer> instance dans un tableau qui est déclaré contenir uniquement List<String> instances. À la ligne 5, nous récupérons l'élément unique de la liste unique de ce tableau. Le compilateur convertit automatiquement l'élément récupéré en String, mais c'est un Integer, donc nous obtenons un ClassCastException au moment de l'exécution. Afin d'éviter cela, la ligne 1 (qui crée un tableau générique) génère une erreur de compilation.

Parce que les tableaux et les génériques ne se combinent pas bien (ainsi que d'autres raisons), il est généralement préférable d'utiliser Collection objets (en particulier List objets) plutôt que des tableaux.

18
Laurence Gonsalves

En général, ce n'est pas une bonne idée de mélanger des génériques et des tableaux en Java, mieux vaut utiliser une ArrayList.

Si vous devez utiliser un tableau, la meilleure façon de gérer cela est de placer la création du tableau (votre exemple 2 ou 3) dans une méthode distincte et de l'annoter avec @SuppressWarnings ("non vérifiée").

5
starblue

La réponse courte semble être que vous ne pouvez vraiment pas.

Voir ce qui suit pour un blog à ce sujet. http://www.bloggingaboutjava.org/2006/01/Java-generics-quirks/

L'un des commentaires du blog indique que:

En fait, les ingénieurs ont rendu illégale la création d'un tel tableau. La création d'un tableau à partir d'une classe générique échoue donc. La méthode Collection.toArray suivie d'un Cast to the Array fonctionne au moment de la compilation.

Cela ne résout pas le problème, à savoir que ArrayStoreCheck ne peut pas être effectué pendant l'exécution, mais vous pouvez créer un tableau de génériques de cette manière.

Comme l'a suggéré Bill le Lézard, vous feriez probablement mieux d'utiliser un

List<Map<String,Integer>>
2
RHSeeger