Bidireccional estructura de datos equivalente multimap

votos
7

Sé que Guavatiene una clase BiMultimap internamente pero no externalizar el código. Necesito una estructura de datos que es bidireccional, es decir, búsqueda por clave y por valor y también acepta duplicados.

es decir algo como esto: (en mi caso, los valores son únicos, pero dos valores pueden apuntar a la misma tecla)

0 <-> 5
1 <-> 10
2 <-> 7
2 <-> 8
3 <-> 11

Quiero ser capaz de get(7)-> volver 2y get(2)volver [7, 8]. ¿Hay otra biblioteca por ahí que tiene una estructura de datos que pueda hacer uso de?

Si no es así, ¿qué sugieres es la mejor opción para manejar este caso? Es mantener dos Multimapsen la memoria de uno con el otro y con una mala práctica?

PD: He leído esta pregunta: mapa de varios valores bidireccional en Java , pero teniendo en cuenta que está fechada en 2011, pensé voy a abrir una pregunta más reciente

Publicado el 20/07/2014 a las 11:12
fuente por usuario
En otros idiomas...                            


2 respuestas

votos
1

Que quieres decir con

Guayaba tiene una clase BiMultimap internamente pero no externalizar el código

El código de una aplicación ya está aquí .

Yo no comprobar si se trata de una aplicación de trabajo, ni si lo hizo en un comunicado o si sólo estoy mirando una especie de instantánea. Todo está a la intemperie, por lo que debe ser capaz de conseguirlo.

De un rápido vistazo al código fuente parece que la aplicación no mantener dos MultMaps, y esto debe estar bien para el caso general.

Respondida el 01/08/2014 a las 05:20
fuente por usuario

votos
0

Si usted no necesita todo el montón de funcionalidad HashBiMultimap guayaba, pero sólo getByKey () y getByValue (), como se ha especificado, puedo sugerir el enfoque, donde sólo una HashMultiMap se utiliza como dispositivo de almacenamiento.

La idea es tratar siempre clave y el valor como objetos de equilibrio y poner a ambos en el mapa de almacenamiento como claves y valores.

Por ejemplo: Que tenemos el siguiente multiMap.put(0, 5), por lo que debemos obtener el mapa de almacenamiento que contiene algo como esto [[key:0, value:5], [key:5, value:0]].

Por lo que necesitamos nuestra BiMultiMap a ser genérica, también es necesario proporcionar algunas clases de envoltura, que deben ser utilizados como parámetros de tipo de mapa de almacenamiento.

Aquí es esta clase de contenedor:

public class ObjectHolder {

    public static ObjectHolder newLeftHolder(Object object) {
        return new ObjectHolder(object, false);
    }

    public static ObjectHolder newRightHolder(Object object) {
        return new ObjectHolder(object, true);
    }

    private Object object;
    private boolean flag;

    private ObjectHolder(Object object, boolean flag) {
        this.object = object;
        this.flag = flag;
    }

    public Object getObject() {

        return object;
    }

    @Override
    public boolean equals(Object o) {

        if (this == o) return true;
        if (!(o instanceof ObjectHolder)) return false;

        ObjectHolder that = (ObjectHolder) o;

        if (flag != that.flag) return false;
        if (!object.equals(that.object)) return false;

        return true;
    }

    @Override
    public int hashCode() {

        int result = object.hashCode();
        result = 31 * result + (flag ? 1 : 0);
        return result;
    }
}

Y aquí está el MultiMap:

public class BiHashMultiMap<L, R> {

    private Map<ObjectHolder, Set<ObjectHolder>> storage;

    public SimpleBiMultiMap() {
        storage = new HashMap<ObjectHolder, Set<ObjectHolder>>();
    }

    public void put(L left, R right) {
        ObjectHolder leftObjectHolder = ObjectHolder.newLeftHolder(left);
        ObjectHolder rightObjectHolder = ObjectHolder.newRightHolder(right);

        put(leftObjectHolder, rightObjectHolder);
        put(rightObjectHolder, leftObjectHolder);
    }

    private void put(ObjectHolder key, ObjectHolder value) {
        if (!storage.containsKey(key)) {
            storage.put(key, new HashSet<ObjectHolder>());
        }
        storage.get(key).add(value);
    }

    public Set<R> getRight(L left) {
        return this.get(ObjectHolder.newLeftHolder(left));
    }

    public Set<L> getLeft(R right) {
        return this.get(ObjectHolder.newRightHolder(right));
    }

    private <V> Set<V> get(ObjectHolder key) {
        Set<ObjectHolder> values = storage.get(key);
        if (values == null || values.isEmpty()) {
            return null;
        }
        Set<V> result = new HashSet<V>();
        for (ObjectHolder value : values) {
            result.add((V)value.getObject());
        }
        return result;
    }
}

Lo que podría parecer extraño es el lefty rightla variable prefijada por todas partes. Se puede pensar en ellos como leftes la llave original, que fue putt para mapear y rightes el valor.

Ejemplo de uso:

BiHashMultiMap<Integer, Integer> multiMap = new BiHashMultiMap<Integer, Integer>();

multiMap.put(0,5);
multiMap.put(1,10);
multiMap.put(2,7);
multiMap.put(3,7);
multiMap.put(2,8);
multiMap.put(3,11);

Set<Integer> left10 = multiMap.getLeft(10); // [1]
Set<Integer> left7 = multiMap.getLeft(7); // [2, 3]
Set<Integer> right0 = multiMap.getRight(0); // [5]
Set<Integer> right3 = multiMap.getRight(3); // [7, 11]

Así que para obtener leftel valor que necesitamos para proveer rightvalor como clave y para obtener rightel valor que necesitamos para proveer leftcomo una clave.

Y, por supuesto, para hacer un mapa de función totalmente necesitamos proporcionar otros métodos, como remove(), contains()y así sucesivamente.

Respondida el 01/08/2014 a las 18:45
fuente por usuario

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more