Estoy buscando una forma de almacenar pares clave-valor. Necesito que la búsqueda sea bidireccional, pero al mismo tiempo necesito almacenar valores múltiples para la misma clave. En otras palabras, algo así como 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 asignar el valor asignado a cada tecla, y para cada valor, obtenga todas las claves asociadas con él.Mapa bidireccional de valores múltiples en Java
Respuesta
¿Necesita soporte para relaciones de muchos a muchos? Lo más cercano que puede obtener es Guava 's Multimap
como @Mechkov escribió - pero más específicamente Multimap
combinación con Multimaps.invertFrom
. "BiMultimap" aún no está implementado, pero está an issue solicitando esta función en la biblioteca de Google Guava.
En este punto se tienen pocas opciones:
Si su "BiMultimap" va a constante inmutable - utilizar
Multimaps.invertFrom
yImmutableMultimap
/ImmutableListMultimap
/ImmutableSetMultimap
(cada uno de theese tres tiene diferentes valores de la colección de almacenamiento). Algo de código (ejemplo tomado de aplicación que desarrollo, utilizaEnum
s) ySets.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 quiere que su Multimapa sea modificable, que será difícil de mantener tanto K-> V y V-> Variantes K a menos que solo modifiques
kToVMultimap
y llames alinvertFrom
cada vez que quieras tener su copia invertida (y haciendo que esa copia no se pueda modificar para asegurarte de que accidentalmente no modifiquevToKMultimap
lo que no actualizaríakToVMultimap
). Esto no es óptimo, pero debería hacerlo en este caso.(¿No es su caso, probablemente, como se ha mencionado bono):
BiMap
interfaz y las clases que implementan tiene.inverse()
método que daBiMap<V, K>
vista desdeBiMap<K, V>
y sí despuésbiMap.inverse().inverse()
. Si this issue que mencioné antes está hecho, probablemente tendrá algo similar.(EDIT de octubre de 2016) También puede utilizar new graph API que estará presente en Guava 20:
En su conjunto, común.gráfico soporta gráficas de las siguientes variedades:
- gráficos dirigidos
- grafos no dirigidos
- nodos y/o bordes con valores asociados (pesos, etiquetas, etc.)
- gráficos que hacen/no hacer permitir la libre bucles
- gráficos que dO/no permiten bordes paralelos (gráficos con bordes paralelos a veces se llaman multigrafos)
- gráficos cuyos nodos/bordes son inserción ordenada, ordenados o no ordenada
Esperanza te tengo
class A {
long id;
List<B> bs;
}
class B {
long id;
List<A> as;
}
¿Qué hay de malo en tener dos mapas, número->> valores, las teclas de la derecha valores-?
Pensé que mantener dos copias de los mismos datos sería más propenso a errores. De todos modos, después de todas las colecciones que he visto, estoy empezando a pensar que es la mejor solución. –
Solo crea un contenedor para los mapas que los mantiene sincronizados. – Stefan
No me gusta el enfoque avalado por esta respuesta. Hay muchas cosas potencialmente incorrectas con esto, incluyendo posiblemente reinventar la rueda, escribir sus propios errores a lo largo del camino, seguridad de la rosca, etc. – bacar
La implementación de Google Guava MultiMap es lo que estoy usando para estos fines.
Map<Key Collection<Values>>
donde Collection puede ser una ArrayList por ejemplo. Permite mapear múltiples valores almacenados en una colección a una clave. Espero que esto ayude!
No es bidireccional. – Stefan
espero usando MultivaluedMap soluciona el problema. Encuentre la documentación del enlace de Oracle a continuación.
http://docs.oracle.com/javaee/6/api/javax/ws/rs/core/MultivaluedMap.html
Esta es una interfaz. ¿Hay alguna implementación? – amoebe
Usando Google guayaba podemos escribir una BiMulitMap primitiva de la siguiente manera.
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 + "]";
}
}
Esperamos que ayude a algunas de las necesidades básicas de la bi-direccional Multi mapa. Tenga en cuenta que K y V deben implementar el método hascode y equals correctamente
- 1. Mapa bidireccional en Java?
- 2. Mapa bidireccional en .NET
- 3. Mapa bidireccional en Cocoa
- 4. ¿Un mapa bidireccional en clojure?
- 5. Mapas con múltiples tipos de valores en java
- 6. Asignación de matriz de Java (valores múltiples)
- 7. Biblioteca de cifrado bidireccional Java
- 8. Múltiples marcadores en un mapa de Google
- 9. Java enum valueOf() con valores múltiples?
- 10. ¿Cómo devolver valores múltiples?
- 11. mapa de Java con claves duplicadas
- 12. Múltiples valores en java.util.Properties
- 13. mapeo bidireccional de Python
- 14. Mapa de claves múltiples en C++
- 15. Diccionario de valores múltiples
- 16. Lista de asignación bidireccional
- 17. SSL bidireccional para servicios web en GAE (java)
- 18. ¿Devolviendo valores múltiples en javascript?
- 19. Valores devueltos múltiples en python
- 20. ¿Cómo "mapa" entre 3 valores?
- 21. convert Mapa valores en Array cadena
- 22. Encontrar los valores más altos de n en un mapa
- 23. Mapa aplicado a múltiples argumentos en Haskell
- 24. colecciones java vs mapa en colecciones framework
- 25. Tabla hash bidireccional en Erlang
- 26. Lista vs Mapa en Java
- 27. scala hashmap valores múltiples
- 28. ¿Cómo usar JPL (interfaz bidireccional Java/Prolog) en Windows?
- 29. ¿Eliminar valores nulos de un mapa?
- 30. MySQL Seleccionar Múltiples VALORES
Habla de la necesidad de tener múltiples valores por clave, pero en su ejemplo no tiene una clave con múltiples valores, sino un valor con dos claves. Probablemente deberías aclarar eso. Si su ejemplo se ajusta a su pregunta, obtendrá mejores respuestas ;-) – pushy
http://www.jguru.com/faq/view.jsp?EID=1317828 aquí puede encontrar cómo crear multimap – maks
@pushy, mismo problema, si invierto el mapa y mantengo los enteros como claves en lugar de como valores, obtengo una asignación de uno a muchos. De todos modos, gracias por la corrección. :) –