Bonne façon d'initialiser HashMap et HashMap peut-il contenir différents types de valeurs?

J'ai donc deux questions sur HashMap s en Java:

  1. Quelle est la bonne façon d'initialiser un HashMap? Je pense qu'il pourrait être préférable dans ma situation d'utiliser:

    HashMap x = new HashMap();
    

    Mais Eclipse continue de suggérer que j'utilise:

    HashMap<something, something> map = new HashMap();
    

    Quel est le meilleur?

  2. Un HashMap peut-il contenir différents types d'objets / types de données en tant que valeurs? Par exemple, cela fonctionnerait-il et serait OK:

    map.put("one", 1);
    map.put("two", {1, 2});
    map.put("three", "hello");
    

    Dans le premier put(), je veux un int, comme une valeur, dans la seconde d'un int[], et troisième une chaîne. Est-ce correct de faire en Java avec HashMaps? Aussi, est-il correct de stocker un HashMap en tant que valeur dans un HashMap?

58
demandé sur jbatista 2009-08-28 20:01:57

8 réponses

Cela dépend vraiment du type de sécurité dont vous avez besoin. La façon non générique de le faire est mieux faite comme:

 Map x = new HashMap();

Remarque que x est tapé comme un Map. cela rend beaucoup plus facile de changer les implémentations (en un TreeMap ou un LinkedHashMap) à l'avenir.

Vous pouvez utiliser des génériques pour assurer un certain niveau de sécurité de type:

Map<String, Object> x = new HashMap<String, Object>();

Dans Java 7 et plus tard, vous pouvez faire

Map<String, Object> x = new HashMap<>();

Ce qui précède, bien que plus verbeux, évite les avertissements du compilateur. Dans ce cas, le contenu de la HashMap peut être tout Object, de sorte que peut être Integer, int[], etc. qui est ce que vous faites.

Si vous utilisez toujours Java 6, les bibliothèques de goyaves (bien qu'il soit assez facile de le faire vous-même) ont une méthode appelée newHashMap() ce qui évite la nécessité de dupliquer les informations de frappe génériques lorsque vous faites un new. Il déduit le type de la déclaration de variable (il s'agit d'une fonctionnalité Java non disponible sur les constructeurs avant Java 7).

En passant, lorsque vous ajoutez un int ou autre primitive, Java l'autoboxe. Cela signifie que le code est équivalent à:

 x.put("one", Integer.valueOf(1));

Vous pouvez certainement mettre un HashMap comme valeur dans un autre HashMap, mais je pense qu'il y a des problèmes si vous le faites récursivement (c'est-à-dire mettre le {[8] } comme valeur en soi).

97
répondu Yishai 2015-05-21 22:28:24

Ceci est une modification faite avec Java 1.5. Ce que vous énumérez en premier est l'ancienne façon, la seconde est la nouvelle façon.

En utilisant HashMap, vous pouvez faire des choses comme:

HashMap<String, Doohickey> ourMap = new HashMap<String, Doohickey>();

....

Doohickey result = ourMap.get("bob");

Si vous n'aviez pas les types sur la carte, vous devriez faire ceci:

Doohickey result = (Doohickey) ourMap.get("bob");

C'est vraiment très utile. Il vous aide à attraper des bugs et éviter d'écrire toutes sortes de moulages supplémentaires. C'était l'une de mes fonctionnalités préférées de 1.5 (et plus récent).

Vous pouvez toujours mettre plusieurs choses dans la carte, spécifiez-la simplement comme carte, puis vous peut mettre n'importe quel objet (une chaîne, une autre carte et un entier, et trois MyObjects si vous êtes si incliné).

14
répondu MBCook 2009-08-28 23:19:32

Eclipse vous recommande de déclarer le type de HashMap car cela impose une certaine sécurité de type. Bien sûr, il semble que vous essayez d'éviter la sécurité de type de votre deuxième partie.

Si vous voulez faire ce dernier, essayez de déclarer map comme HashMap<String,Object>.

4
répondu Paul Tomblin 2009-08-28 16:05:30

La façon dont vous l'écrivez est équivalente à

HashMap<Object, Object> map = new HashMap<Object, Object>();

Ce qui se passe entre parenthèses, c'est que vous communiquez au compilateur ce que vous allez mettre dans le HashMap afin qu'il puisse vérifier les erreurs pour vous. Si Object, Object est ce que vous voulez réellement (probablement pas), vous devriez le déclarer explicitement. En général, vous devriez être aussi explicite que possible avec la déclaration pour faciliter la vérification des erreurs par le compilateur. Ce que vous avez décrit devrait probablement être déclaré comme ce:

HashMap<String, Object> map = new HashMap<String, Object>();

De cette façon, vous déclarez au moins que vos clés seront des chaînes, mais vos valeurs peuvent être n'importe quoi. Rappelez-vous juste d'utiliser une distribution lorsque vous obtenez une valeur de retour.

3
répondu Graphics Noob 2009-08-28 16:21:42

Le 2ème utilise des génériques qui sont venus avec Java 1.5. Cela réduira le nombre de casts dans votre code et peut vous aider à détecter les erreurs à compiletime au lieu de runtime. Cela dit, Cela dépend de ce que vous codez. Une carte rapide et sale pour contenir quelques objets de différents types n'a pas besoin de génériques. Mais si la carte contient des objets qui descendent tous d'un type autre que Object, cela peut en valoir la peine.

L'affiche précédente est incorrecte à propos du tableau dans une carte. Un tableau est en fait un objet, de sorte qu'il est une valeur valide.

Map<String,Object> map = new HashMap<String,Object>();
map.put("one",1); // autoboxed to an object
map.put("two", new int[]{1,2} ); // array of ints is an object
map.put("three","hello"); // string is an object

En outre, comme HashMap est un objet, il peut également s'agir d'une valeur dans un HashMap.

2
répondu Billy Bob Bain 2009-08-28 16:27:04

Un HashMap peut contenir n'importe quel objet en tant que valeur, même s'il s'agit d'un autre HashMap. Eclipse suggère que vous déclarez les types car c'est la pratique recommandée pour les Collections. sous Java 5. Vous êtes libre d'ignorer les suggestions D'Eclipse.

Sous Java 5, Un int (ou tout type primitif) sera autoboxed dans un entier (ou un autre type correspondant) lorsque vous l'ajoutez à une collection. Soyez prudent avec cela, car il y a quelques prises à l'aide de l'autoboxing.

1
répondu Ken Liu 2009-08-28 16:08:44

Eclipse vous suggère de définir generic type afin que vous puissiez avoir type safety. Vous pouvez écrire

Map m = new HashMap();

Qui n'assure pas la sécurité de type mais qui suit assurera la sécurité de type

Map<Object,Object> = new HashMap<Object,Object>();

Le Object peut être n'importe quel type comme les String, Integer etc.

1
répondu 2016-09-09 04:30:03

En réponse à votre deuxième question: oui, un HashMap peut contenir différents types d'objets. Que ce soit une bonne idée ou non dépend du problème que vous essayez de résoudre.

Cela dit, votre exemple ne fonctionnera pas. La valeur int n'est pas un objet. Vous devez utiliser la classe Integer wrapper pour stocker une valeur int dans un HashMap

0
répondu Luke 2009-08-28 16:14:53