web-dev-qa-db-fra.com

Manière correcte d'initialiser HashMap et HashMap peut-il contenir différents types de valeur?

J'ai donc deux questions sur HashMaps en Java:

  1. Quelle est la bonne façon d’initialiser un HashMap? Je pense qu'il serait 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();
    

    Ce qui est mieux?

  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-il OK?

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

    Dans le premier put(), je veux un int comme valeur, dans le second un int[] Et un troisième une chaîne. Est-ce correct de faire dans Java avec HashMaps?? Est-il également acceptable de stocker un HashMap en tant que valeur dans un HashMap?

61
Tony Stark

Cela dépend vraiment du type de sécurité dont vous avez besoin. La meilleure façon de procéder est la suivante:

 Map x = new HashMap();

Notez que x est saisi en tant que Map. cela facilite beaucoup le changement d'implémentations (en TreeMap ou en LinkedHashMap) dans le futur.

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 détaillé, évite les avertissements du compilateur. Dans ce cas, le contenu de HashMap peut être n'importe lequel Object, de sorte qu'il peut s'agir de Integer, int[], Etc., ce que vous faites.

Si vous utilisez toujours Java 6, bibliothèques Guava (bien que ce soit assez facile à faire vous-même) a une méthode appelée newHashMap() , ce qui évite de dupliquer les informations de typage génériques lorsque vous effectuez un new. Il déduit le type de la déclaration de variable (il s'agit d'une Java non disponible sur les constructeurs antérieurs à Java 7).

Soit dit en passant, lorsque vous ajoutez une primitive int ou une autre primitive, Java le remplace automatiquement. Cela signifie que le code est équivalent à:

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

Vous pouvez certainement mettre HashMap comme valeur dans un autre HashMap, mais je pense qu’il ya des problèmes si vous le faites de manière récursive (c’est-à-dire que HashMap est une valeur en soi. ).

100
Yishai

Ceci est une modification effectuée avec Java 1.5. Ce que vous listez en premier est l’ancien, le second est le nouveau.

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. Cela vous aide à attraper les 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 insérer plusieurs éléments dans la carte, il suffit de le spécifier en tant que Carte, puis vous pouvez insérer n'importe quel objet (une chaîne, une autre carte et un entier, et trois MyObjects si vous êtes si enclin à le faire).

14
MBCook

Eclipse vous recommande de déclarer le type de HashMap car cela impose un type de sécurité. Bien entendu, il semblerait que vous essayiez d'éviter la sécurité de type de votre deuxième partie.

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

4
Paul Tomblin

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

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

Entre parenthèses, vous communiquez au compilateur ce que vous allez mettre dans HashMap pour qu'il puisse vérifier les erreurs pour vous. Si Object, Object correspond à ce que vous voulez réellement (probablement pas), vous devez 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é ainsi:

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

De cette façon, vous déclarez au moins que vos clés vont être des chaînes, mais vos valeurs peuvent être n'importe quoi. Rappelez-vous simplement d'utiliser un casting lorsque vous récupérez une valeur.

3
Graphics Noob

Le second utilise des génériques fournis avec Java 1.5. Cela réduira le nombre de conversions dans votre code et peut vous aider à détecter les erreurs au moment de la compilation plutôt que de l'exécution. Cela dit, cela dépend Une carte rapide et sale pouvant contenir quelques objets de types différents 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 sur le tableau dans une carte. Un tableau est en fait un objet, donc c'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

De plus, HashMap étant un objet, il peut également s'agir d'une valeur dans HashMap.

2
Billy Bob Bain

Eclipse vous suggère de définir generic type afin que vous puissiez avoir type safety. Tu peux é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 tel que String, Integer etc.

1
user6811894

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 de déclarer les types, car il s'agit de 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 de primitif) sera sélection automatique dans un entier (ou un autre type correspondant) lorsque vous l'ajoutez à une collection. Faites attention avec cela cependant, car il y a quelques captures à utiliser l'autoboxing.

1
Ken Liu

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 wrapper Integer pour stocker une valeur int dans un HashMap

0
Luke