Tengo una matriz 2D de enteros. Quiero que se incluyan en un HashMap. Pero quiero acceder a los elementos del HashMap basado en Array Index. Algo como:
Para A [2] [5], map.get(2,5)
que devuelve un valor asociado con esa clave. Pero, ¿cómo creo un hashMap con un par de claves? O en general, múltiples claves: Map<((key1, key2,..,keyN), Value)
de manera que pueda acceder al elemento usando get (key1, key2, ... keyN).
EDITAR: 3 años después de publicar la pregunta, quiero agregarle un poco más
Me encontré con otro camino para NxN matrix
.
Índices de matriz, i
y j
se pueden representar como uno solo de key
la siguiente manera:
int key = i * N + j;
//map.put(key, a[i][j]); // queue.add(key);
Y los índices se pueden recuperar de la key
siguiente manera:
int i = key / N;
int j = key % N;
Respuestas:
Hay varias opciones:
2 dimensiones
Mapa de mapas
Objeto de clave de envoltura
Implementar
equals()
yhashCode()
es crucial aquí. Entonces simplemente usa:y:
Table
de GuayabaTable
utiliza mapa de mapas debajo.N dimensiones
Tenga en cuenta que la
Key
clase especial es el único enfoque que escala a n dimensiones. También puede considerar:pero eso es terrible desde la perspectiva del rendimiento, así como la legibilidad y la corrección (no es una manera fácil de hacer cumplir el tamaño de la lista).
Tal vez eche un vistazo a Scala donde tiene tuplas y
case
clases (reemplazando toda laKey
clase con una sola línea).fuente
Map.Entry<K, V>
como clave?Map<Pair<Key1, Key2>, Value>
?hashCode()
también se puede implementar con una sola línea comoObjects.hash(x,y)
Cuando crea su propio objeto de par de claves, debe enfrentar algunas cosas.
Primero, debe tener en cuenta la implementación de
hashCode()
yequals()
. Necesitará hacer esto.En segundo lugar, al implementarlo
hashCode()
, asegúrese de comprender cómo funciona. El ejemplo de usuario dadoes en realidad una de las peores implementaciones que puede hacer. La razón es simple: ¡tienes muchos hashes iguales! Y
hashCode()
debería devolver valores int que tienden a ser raros, únicos en el mejor de los casos. Usa algo como esto:Esto es rápido y devuelve hashes únicos para claves entre -2 ^ 16 y 2 ^ 16-1 (-65536 a 65535). Esto encaja en casi cualquier caso. Muy rara vez estás fuera de estos límites.
En tercer lugar, al implementar
equals()
también debes saber para qué se usa y ser consciente de cómo creas tus claves, ya que son objetos. A menudo hace declaraciones innecesarias porque siempre tendrá el mismo resultado.Si crea claves como esta:
map.put(new Key(x,y),V);
nunca comparará las referencias de sus claves. Porque cada vez que quieras acceder al mapa, harás algo comomap.get(new Key(x,y));
. Por lo tantoequals()
, no necesita una declaración comoif (this == obj)
. Será no aparecer dentro.En lugar de
if (getClass() != obj.getClass())
en suequals()
mejor usoif (!(obj instanceof this))
. Será válido incluso para subclases.Entonces, lo único que necesita comparar es en realidad X e Y. Entonces, la mejor
equals()
implementación en este caso sería:Entonces, al final, su clase clave es así:
Puede dar sus índices de dimensión
X
yY
un nivel de acceso público, ya que son definitivos y no contienen información sensible. No estoy 100% seguro de si elprivate
nivel de acceso funciona correctamente en cualquier caso cuando se envíaObject
a unKey
.Si se pregunta acerca de las finales, declaro cualquier cosa como final cuyo valor se establece en la instanciación y nunca cambia, y por lo tanto es una constante de objeto.
fuente
No puede tener un mapa hash con varias claves, pero puede tener un objeto que tome varios parámetros como clave.
Cree un objeto llamado Índice que tome un valor xey.
Entonces tienes tu
HashMap<Index, Value>
para obtener tu resultado. :)fuente
hashCode
yequals
.Implementado en colecciones comunes MultiKeyMap
fuente
Dos posibilidades. Utilice una clave combinada:
O un mapa de mapa:
fuente
hashCode
yequals
métodos.Utilice
Pair
como claves para elHashMap
. JDK no tiene par, pero puede usar una biblioteca de terceros como http://commons.apache.org/lang o escribir una etiqueta de par por su cuenta.fuente
Cree una clase de valor que represente su clave compuesta, como:
teniendo cuidado de anular
equals()
yhashCode()
correctamente. Si eso le parece mucho trabajo, podría considerar algunos contenedores genéricos listos para usar, comoPair
proporcionados por apache commons, entre otros.También hay muchas preguntas similares aquí, con otras ideas, como usar Guava's Tabla , aunque permite que las claves tengan diferentes tipos, lo que podría ser excesivo (en uso de memoria y complejidad) en su caso, ya que entiendo que sus claves son ambas enteras.
fuente
Si son dos enteros, puedes probar un truco rápido y sucio:
Map<String, ?>
usar la tecla comoi+"#"+j
.Si la clave
i+"#"+j
es la misma quej+"#"+i
intentarmin(i,j)+"#"+max(i,j)
.fuente
String
con divertidas consecuencias.i#j = j#i
sii == j
lo hace, elmin/max
truco no servirá.5#5
y5#5
intercambiado?5#3
tener el mismo hash como3#5
, luego usas min / max para hacer cumplir3#5
en este orden.También puedes usar Guayaba Table implementación de para esto.
La tabla representa un mapa especial donde se pueden especificar dos claves de manera combinada para hacer referencia a un solo valor. Es similar a crear un mapa de mapas.
fuente
Podrías crear tu objeto clave de esta manera:
MapKey de clase pública {
}
La ventaja de esto es: siempre se asegurará de que esté cubriendo todos los escenarios de Iguales también.
NOTA : su key1 y key2 deben ser inmutables. Solo entonces podrá construir un Objeto clave estable.
fuente
podemos crear una clase para pasar más de una clave o valor y el objeto de esta clase se puede utilizar como parámetro en el mapa.
fuente
Puede descargarlo desde el siguiente enlace: https://github.com/VVS279/DoubleKeyHashMap/blob/master/src/com/virtualMark/doubleKeyHashMap/DoubleKeyHashMap.java
https://github.com/VVS279/DoubleKeyHashMap
Puede usar doble clave: valor hashmap,
fuente