titledborder - Mapa bidireccional multivalor en Java
titledborder java (6)
Estoy buscando una manera de almacenar pares clave-valor. Necesito que la búsqueda sea bidireccional, pero al mismo tiempo necesito almacenar varios valores para la misma clave. En otras palabras, algo como un BidiMap, pero para cada clave puede haber múltiples valores. Por ejemplo, debe ser capaz de mantener pares como: "s1" -> 1, "s2" -> 1, "s3" -> 2, y necesito poder obtener el valor asignado a cada tecla, y Para cada valor, obtenga todas las claves asociadas a él.
¿Qué tiene de malo tener dos mapas, claves-> valores, valores-> claves?
Espero que el uso de MultivaluedMap resuelva el problema. Por favor encuentre la documentación de oracle debajo del enlace.
http://docs.oracle.com/javaee/6/api/javax/ws/rs/core/MultivaluedMap.html
Espero te tengo bien
class A {
long id;
List<B> bs;
}
class B {
long id;
List<A> as;
}
La implementación de Guava MultiMap de Google es lo que estoy usando para estos fines.
Map<Key Collection<Values>>
donde Colección puede ser un ArrayList por ejemplo. Permite que múltiples valores almacenados en una colección se asignen a una clave. ¡Espero que esto ayude!
Usando Google Guava podemos escribir un BiMulitMap primitivo como se muestra a continuación.
import java.util.Collection;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap;
public class BiMultiMap<K,V> {
Multimap<K, V> keyToValue = ArrayListMultimap.create();
Multimap<V, K> valueToKey = ArrayListMultimap.create();
public void putForce(K key, V value) {
keyToValue.put(key, value);
valueToKey.put(value, key);
}
public void put(K key, V value) {
Collection<V> oldValue = keyToValue.get(key);
if ( oldValue.contains(value) == false ) {
keyToValue.put(key, value);
valueToKey.put(value, key);
}
}
public Collection<V> getValue(K key) {
return keyToValue.get(key);
}
public Collection<K> getKey(V value) {
return valueToKey.get(value);
}
@Override
public String toString() {
return "BiMultiMap [keyToValue=" + keyToValue + ", valueToKey=" + valueToKey + "]";
}
}
Espero que esto ayude a algunas necesidades básicas del Mapa Multi bidireccional. Tenga en cuenta que K y V necesitan implementar el método hascode y equals correctamente
¿Entonces necesitas apoyo para las relaciones de muchos a muchos? Lo más cercano que puede obtener es el Multimap
Guava como escribió @Mechkov, pero más específicamente la combinación de Multimaps.invertFrom
con Multimaps.invertFrom
. "BiMultimap" aún no está implementado, pero hay un problema al solicitar esta función en la biblioteca de Google Guava.
En este punto tienes pocas opciones:
Si su "BiMultimap" va a una constante inmutable, use
Multimaps.invertFrom
yImmutableMultimap
/ImmutableListMultimap
/ImmutableSetMultimap
(cada uno de estos tres tiene diferentes valores de almacenamiento de colección). Algún código (ejemplo tomado de la aplicación que desarrollo, usaEnum
sySets.immutableEnumSet
):public class RolesAndServicesMapping { private static final ImmutableMultimap<Service, Authority> SERVICES_TO_ROLES_MAPPING = ImmutableMultimap.<Service, Authority>builder() .put(Service.SFP1, Authority.ROLE_PREMIUM) .put(Service.SFP, Authority.ROLE_PREMIUM) .put(Service.SFE, Authority.ROLE_EXTRA) .put(Service.SF, Authority.ROLE_STANDARD) .put(Service.SK, Authority.ROLE_STANDARD) .put(Service.SFP1, Authority.ROLE_ADMIN) .put(Service.ADMIN, Authority.ROLE_ADMIN) .put(Service.NONE, Authority.ROLE_DENY) .build(); // Whole magic is here: private static final ImmutableMultimap<Authority, Service> ROLES_TO_SERVICES_MAPPING = SERVICES_TO_ROLES_MAPPING.inverse(); // before guava-11.0 it was: ImmutableMultimap.copyOf(Multimaps.invertFrom(SERVICES_TO_ROLES_MAPPING, HashMultimap.<Authority, Service>create())); public static ImmutableSet<Authority> getRoles(final Service service) { return Sets.immutableEnumSet(SERVICES_TO_ROLES_MAPPING.get(service)); } public static ImmutableSet<Service> getServices(final Authority role) { return Sets.immutableEnumSet(ROLES_TO_SERVICES_MAPPING.get(role)); } }
Si realmente desea que su Multimap sea modificable, será difícil mantener las variantes K-> V y V-> K a menos que solo esté modificando
kToVMultimap
y llame ainvertFrom
cada vez que desee tener su copia invertida (y hacer que copia no modificable para asegurarte de que accidentalmente no modificasvToKMultimap
lo que no actualizaríakToVMultimap
). Esto no es óptimo pero debería hacer en este caso.(Probablemente no sea su caso, se menciona como un bono): la interfaz
BiMap
y las clases de implementación tienen el método.inverse()
que le da aBiMap<V, K>
vista desdeBiMap<K, V>
y a sí mismo después debiMap.inverse().inverse()
. Si se soluciona este problema que mencioné anteriormente, probablemente tendrá algo similar.(EDITAR en octubre de 2016) También puede usar la nueva API gráfica que estará presente en Guava 20 :
En su conjunto, common.graph admite gráficos de las siguientes variedades:
- graficas dirigidas
- gráficos no dirigidos
- Nodos y / o aristas con valores asociados (pesos, etiquetas, etc.)
- Gráficos que permiten / no permiten auto-bucles.
- gráficos que permiten / no permiten bordes paralelos (los gráficos con bordes paralelos a veces se llaman multigraphs)
- Gráficos cuyos nodos / bordes están ordenados por inserción, ordenados o desordenados