2009-12-29 6 views
0

J'ai un problème avec hashtable java. Voici ma clé et mes valeurs hachablesProblème Java Hashtable

{corpus \ 2.txt = [moineau de chat], corpus \ 4.txt = [moineau d'éléphant], corpus \ 1.txt = [vache d'éléphant], corpus \ 3.txt = [chat de vache]}

Donc si je veux accéder au premier tuple je dois passer la clé "corpus \ 2.txt" pour obtenir sa valeur. Si je passe la valeur je peux obtenir c'est la clé. Mais je veux faire une fonction que je passe comme 1 2 3 4 etc. et obtenir à la fois la clé et la valeur. Une idée?

2ème question: Est-il possible de stocker un index avec clé et valeur? Ou est-il possible d'obtenir l'index (0,1,2,3 etc.) de la hashtable existante?

Merci!

Répondre

3

Pour commencer, je voudrais utiliser un HashMap, plutôt que le (maintenant obsolète) HashTable. Si vous faites cela, alors vous pouvez utiliser Map.Entry pour retourner une paire clé/valeur (selon votre première question).

Vous ne pouvez pas facilement stocker un index avec votre clé. Vous pouvez créer un objet clé spéciale ainsi:

public class Key { 
    private String name; 
    private int index; 
    .... 
} 

avec une mise en œuvre appropriée equals()/hashCode() (comme indiqué ci-dessous dans les commentaires) et l'utiliser comme la clé dans votre HashMap. Vous devez effectuer une recherche à l'aide de cette clé et en construire une à partir de votre clé en cours, mais je ne pense pas que ce soit un gros problème.

+0

Vous devez implémenter (correctement) hashCode et égal - si vous le basez uniquement sur le membre d'index, vous pouvez l'utiliser comme un "index" piraté dans votre carte de hachage. –

+0

@Steven - thx pour le mettre en évidence. J'ai modifié de façon appropriée. –

+0

c'est pourquoi je n'aime pas Java. dans d'autres langues, vous résolvez ce problème en utilisant des tuples, qui implémentent la comparaison, l'égalité, et le hashcode pour vous – Claudiu

0

Il n'existe aucune méthode dans l'API pour obtenir une entrée spécifique à partir d'une table de hachage Java. Vous pouvez accéder à la collection de toutes les entrées avec la méthode entrySet, et répéter que vous obtiendrez toutes les paires clé-valeur en tant qu'objets Map.Entry.

Les tables de hachage sont complètement non ordonnées. Ils ne sont que des mappages des clés aux valeurs et n'ont pas d'indices définis. Il y a un ordre spécifique que les entrées seront traitées si vous itérez sur le résultat entrySet, mais cela peut également changer lorsque vous modifiez la table de hachage.

0

Jetez un oeil à LinkedHashMap, une implémentation de la carte qui préserve l'ordre de saisie.

+0

Peut-être qu'il n'a pas de 'corpus5.txt', mais fait un' corpus6.txt'. – BalusC

0

Utilisez plutôt un Map<Integer, ValueObject> dans lequel ValueObject est juste une classe javabéenne personnalisée avec deux propriétés, par ex. filename et description.

exemple de base coup d'envoi:

public class ValueObject { 
    private String filename; 
    private String description; 

    public ValueObject() { 
     // Always keep default constructor alive. 
    } 

    public ValueObject(String filename, String description) { 
     this.filename = filename; 
     this.description = description; 
    } 

    // Add/generate public getters and setters for filename and description. 
} 

que vous pouvez utiliser comme suit:

Map<Integer, ValueObject> map = new HashMap<Integer, ValueObject>(); 
map.put(1, new ValueObject("corpus1.txt", "elephant cow")); 
map.put(2, new ValueObject("corpus2.txt", "cat sparrow")); 
map.put(3, new ValueObject("corpus3.txt", "cow cat")); 
map.put(4, new ValueObject("corpus4.txt", "elephant sparrow")); 

ValueObject vo = map.get(1); // Returns VO with corpus1.txt and elephant cow. 
0

Il n'y a pas moyen d'accéder à une carte par index.Cependant, si ce que vous voulez vraiment faire est d'accéder aux paires clé-valeur dans la carte un par un, vous pouvez juste faire:

for (Map.Entry<String, List<String>> nameAndWords: hashmap) { 
    String name = nameAndWords.getKey(); 
    List<String> words = nameAndWords.getValue(); 
    // do your stuff here 
} 

Si vous avez réellement besoin d'indexation, vous pouvez ajouter une commande externe à la carte en gardant les clés dans une liste, qui doit être mis à jour lorsque vous modifiez la carte:

HashMap<String, List<String>> wordsByCorpus; 
List<String> corpusNames; 

public void addCorpus(String name, List<String> words) { 
    List<String> oldValue = wordsByCorpus.put(name, words); 
    if (oldValue == null) corpusNames.add(name); 
} 

public void removeCorpus(String name) { 
    wordsByCorpus.remove(name); 
    corpusNames.remove(name); 
} 

public Map.Entry<String, List<String>> getCorpus(int i) { 
    String name = corpusNames.get(i); 
    List<String> words = wordsByCorpus.get(name); 
    return wordsByCorpus.new SimpleImmutableEntry(name, words); // 1.6 only! 
} 
0

soit vous voulez utiliser un LinkedHashMap qui vous permet d'accéder à des valeurs ajoutées à la carte en utilisant l'indice de l'ordre dans lequel ils ont été ajouté.

Ou vous voulez utiliser 2 HashMaps. Un pour indexer par la valeur de chaîne et le second pour convertir la valeur entière en la clé de valeur de chaîne de la première carte. Ensuite, simple à obtenir la clé et la valeur de l'index:

String key = mapByIntToStringKey.get(index); 
V value = mapByStringKey.get(key); 
// now have both key and value, no linear searching so should be fast 

Ainsi vos cartes contiendraient: mapByStringKey = {corpus \ 2.txt = [moineau chat], corpus \ 4.txt = [moineau éléphant], corpus \ 1.txt = [vache éléphant], corpus \ 3.txt = [chat de vache]}

mapByIntToStringKey {2 = corpus \ 2.txt, 4 = corpus \ 4.txt, 1 = corpus \ 1.txt }

bien que cela suppose que toutes vos clés ne sont pas simplement "corpus" + index + ". Txt". Si toutes les clés sont comme ci-dessus alors si les index ne sont pas clairsemés, vous pouvez utiliser un ArrayList simple (mentionné précédemment) et utiliser get (index) qui est rapide (directement dans un tableau, ne peut pas obtenir beaucoup plus rapide que cela), puis reconstruire la clé de chaîne en utilisant l'expression ci-dessus. Si les index sont clairsemés (certains sont manquants, il existe des espaces vides), utilisez simplement mapByIntToStringKey mais remplacez par mapByIntToValue et reconstruisez toute clé de chaîne dont vous avez besoin en utilisant l'expression de chaîne précédente.

La haute réponse actuelle me semble très étrange, en ce sens que la suggestion est de saisir la carte en utilisant le bit d'index int seulement d'une clé composée. Si je ne le lis pas correctement, cela signifie que vous perdez la possibilité de rechercher des valeurs dans la carte à l'aide de la clé de chaîne seule ou peut-être que vous pouvez toujours en déduire l'indice int à partir de la clé de chaîne.