2010-08-07 3 views
54

Ho bisogno di una struttura dati per memorizzare coppie di valori stringa-int in una relazione 1: 1, e anche in grado di cercare da entrambi i lati la loro controparte.Come creare una mappa a 2 vie in java

Ho scritto una classe con una matrice Hashtable e una stringa e ho memorizzato i dati 2 volte e ho utilizzato le funzioni incorporate per la ricerca.

La mia domanda è che c'è un modo più bello per realizzare questo? E meglio intendo essere efficiente e non memorizzare i dati 2 volte, e preferibilmente senza scrivere una tonnellata di codice: P.

+0

Vedere questa risposta semplice http://stackoverflow.com/a/39329515/5466401 –

+0

Eventuali duplicati di [fa Java hanno un HashMap con la ricerca inversa?] (http://stackoverflow.com/questions/1670038/does-java-have-a-hashmap-with-reverse-lookup) – blahdiblah

risposta

51

Sembra che tu stia cercando un bimap.

Le raccolte Google (ora una parte di Guava) contengono un'interfaccia BiMap con alcune implementazioni.

Dalla documentazione BiMap:

A bimap (o "mappa bidirezionale") è una mappa che conserva l'unicità di suoi valori così come quella dei suoi chiavi. Questo vincolo consente a bimaps di supportare una "vista inversa", che è un'altra bimap contenente le stesse voci come questa bimap ma con chiavi e valori invertiti .

Procedimento BiMap.inverse sembra restituire un Map con i valori come chiavi e le chiavi come i valori, in modo che Map può essere utilizzato per chiamare get sul valore e recuperare una chiave.

Inoltre, il numero Map restituito da inverse è una visualizzazione dei dati sottostanti, quindi non è necessario eseguire copie aggiuntive dei dati originali.

Dalla documentazione BiMap.inverse metodo:

Restituisce la vista inverso di questo bimap, che mappa ciascuno di valori di questo bimap al suo tasto associato. Le due bimaps sono supportate dagli stessi dati; le eventuali modifiche ad uno verranno visualizzate nell'altro .

4

Il Google Collections Framework ha un BiMap che fa quello che vuoi.

+0

sì che lo fa! Non sono riuscito a trovare nulla cercando la "mappa a 2 direzioni": P sembra che la mappa bidirezionale sia il termine giusto – sekmet64

-4

Creare una mappa di hash che mappa Object to Object - quindi è possibile utilizzare la stessa mappa per memorizzare String -> Integer e Integer -> String.

Quando aggiungi una stringa/coppia int aggiungi semplicemente entrambi i modi alla stessa mappa.

+3

Questa non è affatto un'implementazione molto ragionevole. Si butta fuori dalla finestra tutti i tipi generici di sicurezza e si aumenta la complessità di tutte le operazioni eseguite sulla mappa aggiungendo due volte voci. Non vi è alcun incapsulamento del meccanismo mediante il quale si sta implementando la mappa bidirezionale. – Tom

+0

@ Tom - Ho scritto la risposta in fretta e ho pensato che l'implementatore sarebbe stato abbastanza ragionevole da avvolgere l'hashmap in una classe che controllava l'accesso ad esso e ha eseguito il casting sui tipi richiesti. Cercherò di essere più chiaro su quel punto in futuro. –

+1

Un altro problema che potresti incontrare è l'archiviazione di A-> B e B-> C, che dovrebbe andare bene con la domanda ma non con la tua risposta. – DerMike

26

È possibile eseguire un'implementazione semplice come questa. Si noti che i dati non vengono copiati in questa implementazione. Solo i riferimenti sono! Ho aggiunto l'implementazione per aggiungere e ottenere. rimuovere e altro metodo di richiesta sono lasciati come esercizio :)

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); 
    } 
} 

e naturalmente le sue applicazioni responsabilità di seguire anche i 'valori' sono unici.Esempio di utilizzo:

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")); 
+2

Sarebbe un approccio interessante in assenza di BiMap di Guava. Tuttavia, suggerirei che questa classe implementasse l'interfaccia Mappa. –

+0

Se hai bisogno di una lezione con l'interfaccia Mappa, puoi sostituire il metodo getBackward con Map inverso(), che restituirà la mappa inversa. –

11

Apache Commons include anche il BidiMap (Mappa bidirezionale).

Definisce una mappa che consente la ricerca bidirezionale tra chiave e valori.

Questa mappa estesa rappresenta una mappatura in cui una chiave può cercare un valore e un valore può cercare una chiave con uguale facilità. Questa interfaccia estende la mappa e può quindi essere utilizzata ovunque sia necessaria una mappa. L'interfaccia fornisce una vista a mappa inversa, consentendo l'accesso completo a entrambe le direzioni di BidiMap.

3

Utilizzando 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")); 

leggere tutorial completo here.