web-dev-qa-db-fra.com

Comment créer une carte bidirectionnelle dans java

J'ai besoin d'une structure de données pour stocker des paires de valeurs chaîne-int dans une relation 1: 1, et pouvoir également rechercher dans les deux sens leur homologue.

J'ai écrit une classe avec une table de hachage et un tableau de chaînes et j'ai stocké les données 2 fois et j'ai utilisé les fonctions intégrées pour la recherche.

Ma question est la suivante: existe-t-il une meilleure façon d'accomplir cela? Et par plus agréable, je veux dire être efficace et ne pas stocker les données 2 fois, et de préférence sans écrire une tonne de code non plus: P.

55
sekmet64

Il semble que vous recherchiez une bimap.

Les collections Google (qui font maintenant partie de Guava ) contiennent une interface BiMap avec quelques implémentations.

Dans la documentation BiMap:

Une bimap (ou "carte bidirectionnelle") est une carte qui préserve l'unicité de ses valeurs ainsi que celle de ses clés. Cette contrainte permet aux bimaps de prendre en charge une "vue inverse", qui est une autre bimap contenant les mêmes entrées que cette bimap mais avec des clés et des valeurs inversées.

Le BiMap.inverse semble renvoyer un Map avec les valeurs comme clés et les clés comme valeurs, afin que Map puisse être utilisé pour appeler get sur la valeur et récupérer une clé.

De plus, le Map renvoyé par inverse est une vue des données sous-jacentes, il n'est donc pas nécessaire de faire des copies supplémentaires des données d'origine.

Du BiMap.inverse documentation sur la méthode:

Renvoie la vue inverse de cette bimap, qui mappe chacune des valeurs de cette bimap à sa clé associée. Les deux bimaps sont soutenus par les mêmes données; toute modification apportée à l'un apparaîtra dans l'autre.

52
coobird

Vous pouvez faire une implémentation simple comme celle-ci. Veuillez noter que les données ne sont pas copiées dans cette implémentation. Seules les références le sont! J'ai ajouté une implémentation pour ajouter et obtenir. supprimer et toute autre méthode requise est laissée comme exercice :)

public class TwoWayHashmap<K extends Object, V extends Object> {

  private Map<K,V> forward = new Hashtable<K, V>();
  private Map<V,K> backward = new Hashtable<V, K>();

  public synchronized void add(K key, V value) {
    forward.put(key, value);
    backward.put(value, key);
  }

  public synchronized V getForward(K key) {
    return forward.get(key);
  }

  public synchronized K getBackward(V key) {
    return backward.get(key);
  }
}

Et bien sûr, la responsabilité de ses applications de garantir même les "valeurs" est unique. Exemple d'utilisation:

TwoWayHashmap twmap = new TwoWayHashmap<String, String>();
twmap.add("aaa", "bbb");
twmap.add("xxx", "yyy");
System.out.println(twmap.getForward("xxx"));
System.out.println(twmap.getBackward("bbb"));
30
Gopi

Apache Commons comprend également le BidiMap (Carte bidirectionnelle).

Définit une carte qui permet une recherche bidirectionnelle entre la clé et les valeurs.

Cette carte étendue représente un mappage dans lequel une clé peut rechercher une valeur et une valeur peut rechercher une clé avec la même facilité. Cette interface étend la carte et peut donc être utilisée partout où une carte est requise. L'interface offre une vue cartographique inversée, permettant un accès complet aux deux directions du BidiMap.

11
Alex B

Google Guava a un BiMap qui fait ce que vous voulez.

5
jqno

En utilisant Guava ,

    HashBiMap<String, String> map = HashBiMap.create();

    map.put("name", "Sohail");
    map.put("country", "Pakistan");

    Log.d("tag", "name is " + map.get("name"));


    BiMap<String, String>invmap= map.inverse();

    Log.d("tag", "Pakistan is a " + invmap.get("Pakistan"));

lire le tutoriel complet ici.

4
SohailAziz