2010-08-07 7 views
54

Necesito una estructura de datos para almacenar pares de valores string-int en una relación 1: 1, y poder también buscar de cualquier manera su contraparte.Cómo crear un mapa de 2 vías en java

Escribí una clase con una Hashtable y una matriz String y almacené los datos 2 veces y usé las funciones integradas para la búsqueda.

Mi pregunta es, ¿existe alguna forma más agradable de lograr esto? Y por más bonito me refiero a ser eficiente y no almacenar los datos 2 veces, y preferiblemente sin escribir una tonelada de código: P.

+0

Ver este simple respuesta http://stackoverflow.com/a/39329515/5466401 –

+0

duplicado posible de [¿El Java tiene un HashMap con búsqueda inversa?] (http://stackoverflow.com/questions/1670038/does-java-have-a-hashmap-with-reverse-lookup) – blahdiblah

Respuesta

51

Parece que usted puede estar buscando un bimap.

Google Collections (ahora parte de Guava) contiene una interfaz BiMap con algunas implementaciones.

De la documentación BiMap:

Un BIMAP (o "mapa bidireccional") es un mapa que preserva la singularidad de sus valores, así como la de sus llaves. Esta restricción permite que las bimaps admitan una "vista inversa", que es otra bimap que contiene las mismas entradas que esta bimap pero con claves y valores invertidos.

El método BiMap.inverse parece devolver un Map con los valores como las claves y las claves como los valores, por lo que Map se puede utilizar para llamar a get en el valor y recuperar una clave.

Además, el Map devuelto por inverse es una vista de los datos subyacentes, por lo que no tiene que hacer copias adicionales de los datos originales.

De la documentación BiMap.inverse método:

Devuelve la vista inversa de esta BIMAP, que mapea cada uno de los valores de este BIMAP a su tecla asociada. Los dos bimaps están respaldados por los mismos datos; cualquier cambio en uno aparecerá en el otro.

-4

Cree un hashmap que mapea Object to Object - entonces puede usar el mismo mapa para almacenar String -> Integer and Integer -> String.

Cuando agrega un par de cadena/int, solo agréguelo en ambos sentidos al mismo mapa.

+3

Esta no es una implementación muy sensata en absoluto. Lanzas todo el tipo genérico de seguridad fuera de la ventana y aumenta la complejidad de todas las operaciones llevadas a cabo en el mapa añadiendo entradas dobles. No hay encapsulamiento del mecanismo por el cual está implementando el mapa bidireccional. – Tom

+0

@Tom - Escribí la respuesta con prisa y asumí que el implementador sería lo suficientemente sensato como para envolver el hashmap en una clase que controlaba el acceso y hacía el casting a los tipos requeridos. Trataré de ser más claro sobre ese punto en el futuro. –

+1

Otro problema con el que podría encontrarse es almacenar A-> B y B-> C, lo cual debería estar bien con la pregunta pero no con su respuesta. – DerMike

26

Puede hacer una implementación simple como esta. Tenga en cuenta que los datos no se copian en esta implementación. Solo las referencias son! He agregado implementación para agregar y obtener. quitar y el otro método requerido se dejan como ejercicio :)

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

Y por supuesto su responsabilidad aplicaciones a producirse incluso los 'valores' son únicos.Ejemplo de uso:

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

Sería un enfoque interesante en ausencia de BiMap de Guava. Sin embargo, sugiero que tenga esta clase implementar la interfaz de Mapa. –

+0

Si necesita clase con la interfaz de Mapa, puede reemplazar el método getBackward con Map inverse(), que devolverá el mapa inverso. –

11

Apache Commons también incluye el BidiMap (Bi direccional mapa).

Define un mapa que permite la búsqueda bidireccional entre clave y valores.

Este mapa extendido representa una asignación donde una clave puede buscar un valor y un valor puede buscar una clave con la misma facilidad. Esta interfaz extiende el mapa y, por lo tanto, puede usarse en cualquier lugar donde se requiera un mapa. La interfaz proporciona una vista de mapa inversa, que permite el acceso completo a ambas direcciones de BidiMap.

3

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

leer completo tutorial here.

Cuestiones relacionadas