Quelle est la différence entre la table de hachage et les objets de la Carte en Java?
Quelle est la différence entre les cartes que j'ai créer (dans une autre question, les gens ont répondu à l'aide de leur apparence, de façon interchangeable, et je me demandais si/comment ils sont différents):
HashMap<String, Object> map = new HashMap<String, Object>();
Map<String, Object> map = new HashMap<String, Object>();
Vous devez vous connecter pour publier un commentaire.
Il n'y a pas de différence entre les objets; vous avez une
HashMap<String, Object>
dans les deux cas. Il y a une différence dans la interface vous avez de l'objet. Dans le premier cas, l'interface estHashMap<String, Object>
, tandis que dans le second c'estMap<String, Object>
. Mais l'objet sous-jacent est le même.L'avantage de l'utilisation de
Map<String, Object>
est que vous pouvez changer l'objet sous-jacent à un autre type de carte sans rupture de votre contrat avec tout le code qui l'utilise. Si vous déclarez queHashMap<String, Object>
, vous devez modifier votre contrat, si vous souhaitez modifier l'implémentation sous-jacente.Exemple: disons que j'écris cette classe:
La classe a un couple de cartes interne de la chaîne->objet qui il partage (via des méthodes accesseur) avec des sous-classes. Disons que je l'écris avec
HashMap
s de départ, parce que je pense que c'est la structure appropriée à utiliser lors de l'écriture de la classe.Plus tard, Marie écrit le code sous-classement. Elle a quelque chose qu'elle doit faire avec les deux
things
etmoreThings
, alors, naturellement, elle le met que dans une méthode commune, et elle utilise le même type que j'ai utilisé surgetThings
/getMoreThings
lors de la définition de sa méthode:Plus tard, je décide qu'en fait, c'est mieux si j'utilise
TreeMap
au lieu deHashMap
dansFoo
. - Je mettre à jourFoo
, l'évolutionHashMap
àTreeMap
. Maintenant,SpecialFoo
ne compile pas plus, parce que j'ai rompu le contrat:Foo
l'habitude de dire qu'il a fourniHashMap
s, mais maintenant c'est leTreeMaps
à la place. Nous avons donc à résoudreSpecialFoo
maintenant (et ce genre de chose peut se propagent par le biais d'une base de code).Sauf si j'ai eu une très bonne raison pour le partage de ma mise a l'aide d'un
HashMap
(et ça arrive), ce que j'aurais fait a été de déclarergetThings
etgetMoreThings
comme juste retourMap<String, Object>
, sans être plus précis que ça. En fait, à moins d'une bonne raison pour faire quelque chose d'autre, même au sein deFoo
je devrais probablement déclarerthings
etmoreThings
commeMap
, pasHashMap
/TreeMap
:Note comment je suis maintenant en utilisant
Map<String, Object>
partout où je le peux, seul être précis, quand je créer des objets réels.Si j'avais fait cela, alors Marie aurait fait ceci:
...et de changer de
Foo
n'aurait pas eu deSpecialFoo
arrêt de la compilation.(Interfaces et les classes de base) nous révèlent qu'autant qu'il est nécessaire, en gardant la flexibilité de nos sous les couvertures pour faire les changements appropriés. En général, nous voulons avoir nos références être aussi simple que possible. Si nous n'avons pas besoin de savoir c'est un
HashMap
, il vous suffit d'appeler unMap
.Ce n'est pas aveugle de la règle, mais en général, de codage à la plus générale de l'interface va être moins cassant que le codage à quelque chose de plus spécifique. Si j'avais de rappeler que, je n'aurais pas créé un
Foo
que défini Marie à l'échec avecSpecialFoo
. Si Marie a rappeler que, même si j'ai foiréFoo
, elle aurait déclaré sa méthode privée avecMap
au lieu deHashMap
et mon changement deFoo
s'contrat n'aurait pas eu des répercussions sur son code.Parfois, vous ne pouvez pas faire cela, parfois, vous avez à être précis. Mais à moins d'avoir une raison d'être, err vers le moins-interface spécifique.
Carte est une interface qui HashMap met en œuvre. La différence est que dans la deuxième mise en œuvre de votre référence à la table de hachage ne permettre l'utilisation des fonctions définies dans l'interface de la Carte, alors que le premier va permettre l'utilisation de toutes les fonctions publiques dans la HashMap (qui comprend l'interface de la Carte).
Il sera probablement plus de sens si vous lisez Soleil interface du tutoriel
Carte a les implémentations suivantes:
HashMap
Map m = new HashMap();
LinkedHashMap
Map m = new LinkedHashMap();
Tree Map
Map m = new TreeMap();
WeakHashMap
Map m = new WeakHashMap();
Supposons que vous ayez créé une méthode (c'est juste pseudo-code).
Supposons que les besoins de votre projet de changement:
HashMap
.HashMap
àLinkedHashMap
.LinkedHashMap
àTreeMap
.Si votre méthode renvoie classes spécifiques au lieu de quelque chose qui met en œuvre la
Map
interface, vous devez changer le type de retour degetMap()
méthode à chaque fois.Mais si vous utilisez le polymorphisme de la fonctionnalité de Java, et au lieu de retourner classes spécifiques, l'utilisation de l'interface
Map
, il améliore code de réutilisabilité et de réduire l'impact des changements d'exigences.J'allais faire un commentaire sur la accepté de répondre, mais elle a eu trop funky (je déteste ne pas avoir des sauts de ligne)
Exactement--et vous voulez toujours utiliser la plus générale de l'interface, vous pouvez éventuellement. Envisager ArrayList vs LinkedList. Énorme différence dans la façon dont vous les utilisez, mais si vous utilisez "Liste", vous pouvez basculer entre eux facilement.
En fait, vous pouvez remplacer le côté droit de l'initialiseur, avec une dynamique d'instruction. comment quelque chose comme cela:
De cette façon, si vous allez remplir la collection avec un tri d'insertion, vous devez utiliser une liste chaînée (une insertion de tri dans un tableau la liste est criminel.) Mais si vous n'avez pas besoin de garder triés et sont juste à la précédente, vous utiliser une ArrayList (Plus efficace pour d'autres opérations).
C'est un assez gros stretch ici parce que les collections ne sont pas le meilleur exemple, mais dans OO conception de l'un des concepts les plus importants est l'aide de l'interface de façade pour accéder à des objets différents, avec exactement le même code.
Modifier répondre à un commentaire:
Comme pour votre carte commentaire ci-dessous, Oui à l'aide de la "Carte" de l'interface restreint aux seuls méthodes, à moins que vous lancez la collection retour de la Carte de HashMap (ce qui va à l'encontre de l'objectif).
Souvent ce que vous allez faire est de créer un objet et de le remplir à l'aide de ce type spécifique (HashMap), dans une sorte de "créer" ou "initialiser" la méthode, mais la méthode renverra une "Carte" qui n'a pas besoin d'être manipulé comme une table de hachage plus.
Si jamais vous avez à jeter par la manière, vous utilisez probablement une mauvaise interface ou votre code n'est pas structuré assez bien. Notez qu'il est acceptable d'avoir une partie de votre code de le traiter comme une "table de hachage", tandis que l'autre considère comme une "Carte", mais cela devrait couler "vers le bas". de sorte que vous ne sont jamais de casting.
Notez également la semi-aspect propre de rôles indiqué par les interfaces. Une LinkedList fait une bonne pile ou file d'attente, une ArrayList qui fait un bon stack, mais une horrible file d'attente (encore une fois, une suppression entraînerait un déplacement de l'ensemble de la liste), de sorte LinkedList implémente l'interface d'Attente, ArrayList n'.
Comme l'a noté TJ Crowder et Adamski, une référence à une interface, l'autre à une mise en œuvre spécifique de l'interface. Selon Joshua Bloc, vous devriez toujours essayer de coder des interfaces, pour vous permettre de mieux gérer les changements sous-jacents de la mise en œuvre - c'est à dire si HashMap soudain n'était pas idéal pour votre solution et vous avez besoin de modifier le plan de mise en œuvre, vous pouvez toujours utiliser l'interface de la Carte, et de changer l'instanciation de type.
Dans votre deuxième exemple de la "carte" de référence est de type
Map
, qui est une interface implémentée parHashMap
(et d'autres types deMap
). Cette interface est un contrat en disant que l'objet des cartes clés à des valeurs et prend en charge diverses activités (par exemple,put
,get
). Il dit rien au sujet de la mise en œuvre de laMap
(dans ce cas, unHashMap
).La deuxième approche est généralement préférable, en général, vous ne voulez pas exposer la carte spécifique de mise en œuvre de méthodes à l'aide de la
Map
ou par l'intermédiaire d'une définition de l'API.Carte est le de type statique de la carte, tandis que la table de hachage est la de type dynamique de la carte. Cela signifie que le compilateur va traiter votre carte de l'objet comme étant un type de Carte, même si au moment de l'exécution, il peut pointer vers n'importe quel sous-type de il.
Cette pratique de la programmation à l'aide d'interfaces au lieu de les implémentations a l'avantage de rester souple: Vous pouvez par exemple remplacer le type dynamique de la carte au moment de l'exécution, tant qu'il est un sous-type de Carte (par exemple, LinkedHashMap), et de modifier le plan du comportement à la volée.
Une bonne règle de base est de rester aussi abstrait que possible sur le niveau de l'API: Si, par exemple, une méthode de programmation doivent travailler sur les cartes, puis il suffit de déclarer un paramètre comme la Carte au lieu de la plus stricte (parce que moins abstraite) de type HashMap. De cette façon, le consommateur de votre API peut être flexible sur ce type de Carte de mise en œuvre qu'ils veulent transmettre à votre méthode.
Vous créez les mêmes cartes.
Mais vous pouvez combler la différence lorsque vous allez l'utiliser. Avec le premier cas, vous serez en mesure d'utiliser des HashMap méthodes (mais je ne me rappelle pas quelqu'un vraiment utile), et vous serez en mesure de passer comme un HashMap paramètre:
Carte est de l'interface et de la table de hachage est une classe qui implémente l'Interface de Carte
Ajouter de la page voté réponse et beaucoup de ceux ci-dessus, soulignant le "plus générique, de mieux", j'aimerais creuser un peu plus.
Map
est la structure de contrat, alors queHashMap
est une mise en œuvre en fournissant ses propres méthodes pour faire face aux différents problèmes réels: comment calculer l'indice, ce qui est de la capacité et de la façon de l'incrémenter, comment insérer, comment garder l'index unique, etc.Nous allons regarder dans le code source:
Dans
Map
nous avons la méthode decontainsKey(Object key)
:JavaDoc:
Il exige sa mise en application, pour la mettre en œuvre, mais le "comment" est à sa liberté, seulement pour s'assurer qu'il retourne corriger.
Dans
HashMap
:Il s'avère que
HashMap
utilise hashcode pour tester si cette carte contient la clé. Donc, il a l'avantage de l'algorithme de hachage.Carte est l'Interface et de la table de hachage est la classe qui implémente cette.
Donc, dans cette application, vous créez les mêmes objets
Table de hachage est une implémentation de la Carte de sorte qu'il est tout à fait le même, mais a "clone()" la méthode que je vois dans le guide de référence))
Tout d'abord
Map
est une interface qu'il a mises en œuvre différentes comme -HashMap
,TreeHashMap
,LinkedHashMap
etc. L'Interface fonctionne comme un super classe pour la mise en œuvre de la classe. Ainsi, selon la programmation orientée objet est la règle concrète de la classe qui implémenteMap
est unMap
aussi. Cela signifie que nous pouvons attribuer/mettre desHashMap
type de variable à uneMap
variable de type sans aucun type de casting.Dans ce cas, nous pouvons attribuer
map1
àmap2
sans aucun moulage ou de toute perte de données -