Hashtable multi-values en Java

Est-il possible d'avoir plusieurs valeurs pour la même clé dans une table de hachage? Dans la négative, pouvez-vous suggérer une classe ou une interface qui pourrait être utilisée?

25
demandé sur Jonik 2009-06-26 19:41:24

13 réponses

Pas de. C'est un peu l'idée des tables de hachage.

cependant, vous pouvez soit rouler votre propre avec un Map<YourKeyObject, List<YourValueObject>> et quelques méthodes d'utilité pour créer la liste si elle n'est pas présente, ou utiliser quelque chose comme le Multimap de collections Google .

exemple:

String key = "hello";
Multimap<String, Integer> myMap = HashMultimap.create();
myMap.put(key, 1);
myMap.put(key, 5000);
System.out.println(myMap.get(key)); // prints either "[1, 5000]" or "[5000, 1]"
myMap = ArrayListMultimap.create();
myMap.put(key, 1);
myMap.put(key, 5000);
System.out.println(myMap.get(key)); // always prints "[1, 5000]"

noter que Multimap n'est pas un exact équivalent de la solution maison; Hashtable synchronise toutes ses méthodes, tandis que Multimap ne fait aucune telle garantie. Cela signifie que l'utilisation d'un Multimap peut vous causer des problèmes si vous l'utilisez sur plusieurs threads . Si votre carte est utilisée sur un seul thread, cela ne fera aucune différence (et vous auriez dû utiliser HashMap au lieu de Hashtable de toute façon).

21
répondu Michael Myers 2009-06-26 16:22:46

valeurs d'une table de hachage est objet afin que vous puissiez stocker une liste

11
répondu Eric 2009-06-26 15:42:58

plutôt que de donner encore une autre réponse multipmap, je vais vous demander pourquoi vous voulez faire cela?

Sont les multiples valeurs qui lui sont associées? Si oui, il est probablement préférable de créer une structure de données pour les contenir. Si non, il est peut-être plus approprié d'utiliser des cartes distinctes.

est-ce que vous les maintenez ensemble pour pouvoir les itérer sur la base de la clé? Vous voudrez peut-être chercher une structure de données d'indexation alternative, comme une liste de lecture.

7
répondu kdgregory 2009-06-26 15:57:47

dans un hashtable, on utilise une paire clé/valeur pour stocker l'information.

en Java, la classe Hashtable accepte une seule valeur pour une seule clé. Ce qui suit est un exemple d'une tentative d'associer plusieurs valeurs à une seule clé:

Hashtable<String, String> ht = new Hashtable<String, String>();

ht.put("Answer", "42");
ht.put("Hello", "World");    // First value association for "Hello" key.
ht.put("Hello", "Mom");      // Second value association for "Hello" key.

for (Map.Entry<String, String> e : ht.entrySet()) {
  System.out.println(e);
}

dans une tentative d'inclure des valeurs multiples ( "World" , "Mom" ) à une seule clé ( "Hello" ), nous finissons avec le résultat suivant pour impression des rubriques dans le Hashtable :

Answer=42
Hello=Mom

la paire clé/valeur de "Hello" et "World" n'est pas dans la Hashtable -- seulement la deuxième entrée "Hello" et " Mom "est dans la Hashtable . Cela montre qu'on ne peut pas avoir des valeurs multiples associées à une seule clé dans un Hashtable .


ce qui est vraiment nécessaire ici est un multimap , ce qui permet une association de valeurs multiples à une seule clé.

une mise en œuvre du multimap est Multimap de collections Google :

Multimap<String, String> mm = HashMultimap.create();

mm.put("Answer", "42");
mm.put("Hello", "World");
mm.put("Hello", "Mom");

for (Map.Entry<String, String> e : mm.entries()) {
  System.out.println(e);
}

c'est similaire à l'exemple ci-dessus qui utilisait Hashtable , mais le comportement est très différent -- un Multimap permet l'association de valeurs multiples à une seule clé. Le résultat de l'exécution du code ci-dessus est comme suit:

Answer=42
Hello=Mom
Hello=World

comme on peut le voir, pour la clé "Hello" , les valeurs de "Mom" et "World" y sont associées. Contrairement à Hashtable , il ne rejette pas une des valeurs et ne la remplace pas par une autre. Le Multimap est capable de s'accrocher à des valeurs multiples pour chaque clé.

6
répondu coobird 2009-06-26 16:36:11

Comme d'autres l'ont souligné, non. Au lieu de cela, envisagez d'utiliser un Multimap qui peut cartographier de nombreuses valeurs pour la même clé.

The Google Collections ( mise à jour : Guava ) bibliothèque contient une mise en œuvre, et est probablement votre meilleur pari.

Edit : bien sûr , vous pouvez faire comme Eric suggère , et stockez une Collection en tant que valeur dans votre Hashtable (ou carte, plus généralement), mais cela signifie écrire vous-même du code inutile. En utilisant une bibliothèque comme Google Collections, il prendrait soin de la "plomberie" de bas niveau pour vous. Regardez ce bel exemple de la façon dont votre code serait simplifié en utilisant Multimap au lieu des classes de Collections Java à la vanille.

5
répondu Jonik 2017-05-23 12:13:53

aucune des réponses n'indiquait ce que je ferais en premier.

le plus grand saut que j'ai fait dans mes capacités OO a été quand j'ai décidé de toujours faire une autre classe quand il semblait qu'il pourrait être même légèrement utile--et c'est une des choses que j'ai appris en suivant ce modèle.

presque tout le temps, je trouve qu'il y a une relation entre les objets que j'essaie de placer dans une table de hachage. Plus souvent que pas, il ya de la place pour une classe--même une méthode ou deux.

en fait, je trouve souvent que je ne veux même pas d'une structure de type HashMap--un simple HashSet fait très bien.

L'élément que vous stockez comme clé primaire peut devenir l'identité d'un nouvel objet--vous pouvez donc créer des méthodes de hachage et de hachage qui ne font référence qu'à un seul objet (eclipse peut faire vos méthodes de hachage et de hachage pour vous facilement). de cette façon, le nouvel objet va enregistrer, trier et récupérer exactement comme votre origine, ensuite, utilisez les propriétés de stocker le reste des éléments.

la plupart du temps quand je fais cela, je trouve qu'il y a quelques méthodes qui vont là aussi bien et avant que je le sache j'ai un objet à part entière qui aurait dû être là tout au long, mais je n'ai jamais reconnu, et un tas de facteurs d'ordures hors de mon code.

afin de le rendre plus "un pas de bébé", je crée souvent la nouvelle classe contenue dans ma classe d'origine--parfois je même contenir la classe dans un méthode si cela a du sens de le définir de cette façon--alors je le déplace à mesure qu'il devient plus clair qu'il devrait s'agir d'une classe de première classe.

4
répondu Bill K 2009-06-26 16:10:54

Juste faire votre propre:

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

à ajouter:

  public void add(String key, Object o) {
    List<Object> list;
    if (multiMap.containsKey(key)) {
      list = multiMap.get(key);
      list.add(o);
    } else {
      list = new ArrayList<Object>();
      list.add(o);
      multiMap.put(key, list);
    }
  }
4
répondu Cambium 2009-06-26 21:00:50

Voir la Google Collections de la Bibliothèque pour multimaps et similaires de telles collections. Les collections intégrées n'ont pas de support direct pour cela.

2
répondu Carl Manaster 2009-06-26 15:45:20

ce que vous cherchez est un Multimap . Le api de collections google fournit une belle mise en œuvre de cela et bien d'autres choses qui valent la peine d'apprendre à utiliser. Fortement recommandé!

2
répondu bendin 2009-06-26 15:57:49

vous devez utiliser quelque chose appelé un MultiMap . Ce N'est pas strictement une carte, mais une API différente. C'est à peu près la même chose qu'une Map>, mais vous n'aurez pas de méthodes comme entrySet() ou values().

1
répondu Mark Renouf 2009-06-26 15:44:16

Simple. Plutôt Hashtable<Key, Value> , utilisez Hashtable<Key, Vector<Value>> .

1
répondu luiscubal 2009-06-26 21:00:50

outre les collections de Google Il ya un apache Commons Collection objet pour MultiMap

0
répondu sheki 2010-10-07 09:12:09

suit le code sans la bibliothèque de goyave de Google. Il est utilisé pour la double valeur comme clé et ordre trié

Map<Double,List<Object>> multiMap = new TreeMap<Double,List<Object>>();

for( int i= 0;i<15;i++)
{
    List<Object> myClassList = multiMap.get((double)i);
    if(myClassList == null)
    {
        myClassList = new ArrayList<Object>();
        multiMap.put((double) i,myClassList);
    }
    myClassList.add("Value "+ i);
}

List<Object> myClassList = multiMap.get((double)0);
if(myClassList == null)
{
    myClassList = new ArrayList<Object>();
    multiMap.put( (double) 0,myClassList);
}
myClassList.add("Value Duplicate");
for (Map.Entry entry : multiMap.entrySet()) 
{
  System.out.println("Key = " + entry.getKey() + ", Value = " +entry.getValue());
}
0
répondu Somnath Kadam 2013-02-14 15:53:14