Eu tenho uma matriz 2D de inteiros. Eu quero que eles sejam colocados em um HashMap. Mas eu quero acessar os elementos do HashMap com base no Array Index. Algo como:
Para A [2] [5], map.get(2,5)
que retorna um valor associado a essa chave. Mas como faço para criar um hashMap com um par de chaves? Ou, em geral, várias chaves: de Map<((key1, key2,..,keyN), Value)
forma que eu possa acessar o elemento usando get (key1, key2, ... keyN).
EDITAR: 3 anos após postar a pergunta, quero acrescentar um pouco mais a ela
Me deparei com outra maneira de NxN matrix
.
Índices de matriz i
e j
podem ser representados como um único key
da seguinte maneira:
int key = i * N + j;
//map.put(key, a[i][j]); // queue.add(key);
E os índices podem ser recuperados da key
seguinte maneira:
int i = key / N;
int j = key % N;
Respostas:
Existem várias opções:
2 dimensões
Mapa de mapas
Objeto de chave de invólucro
Implementar
equals()
ehashCode()
é crucial aqui. Então você simplesmente usa:e:
Table
de goiabaTable
usa mapa de mapas embaixo.N dimensões
Observe que a
Key
classe especial é a única abordagem que pode ser dimensionada para n dimensões. Você também pode considerar:mas isso é terrível do ponto de vista do desempenho, bem como legibilidade e correção (nenhuma maneira fácil de impor o tamanho da lista).
Talvez dê uma olhada no Scala onde você tem tuplas e
case
classes (substituindo aKey
classe inteira por uma linha).fonte
Map.Entry<K, V>
como chave?Map<Pair<Key1, Key2>, Value>
?hashCode()
também pode ser implementado com uma única linha comoObjects.hash(x,y)
Ao criar seu próprio objeto de par de chaves, você deve enfrentar algumas coisas.
Primeiro, você deve estar ciente de como implementar
hashCode()
eequals()
. Você precisará fazer isso.Em segundo lugar, ao implementar
hashCode()
, certifique-se de entender como funciona. O exemplo de usuário fornecidoé na verdade uma das piores implementações que você pode fazer. A razão é simples: você tem muitos hashes iguais! E o
hashCode()
deve retornar valores int que tendem a ser raros, únicos na melhor das hipóteses. Use algo assim:Isso é rápido e retorna hashes exclusivos para chaves entre -2 ^ 16 e 2 ^ 16-1 (-65536 a 65535). Isso se encaixa em quase todos os casos. Muito raramente você está fora desses limites.
Terceiro, ao implementar
equals()
também saiba para que serve e esteja ciente de como você cria suas chaves, uma vez que são objetos. Freqüentemente, você faz coisas desnecessárias se as declarações causam, você sempre terá o mesmo resultado.Se você criar chaves como esta:
map.put(new Key(x,y),V);
você nunca comparará as referências de suas chaves. Porque toda vez que você quiser acessar o mapa, você fará algo parecidomap.get(new Key(x,y));
. Portanto, vocêequals()
não precisa de uma declaração comoif (this == obj)
. Isso nunca vai acontecer .Em vez de
if (getClass() != obj.getClass())
em seuequals()
melhor usoif (!(obj instanceof this))
. Será válido até mesmo para subclasses.Então, a única coisa que você precisa comparar é realmente X e Y. Portanto, a melhor
equals()
implementação neste caso seria:Então, no final, sua aula principal é assim:
Você pode fornecer seus índices de dimensão
X
eY
um nível de acesso público, pois são finais e não contêm informações confidenciais. Não tenho 100% de certeza se oprivate
nível de acesso funciona corretamente em qualquer caso ao transmitir oObject
para umKey
.Se você quer saber sobre as finais, eu declaro qualquer coisa como final cujo valor é definido na instanciação e nunca muda - e, portanto, é uma constante de objeto.
fonte
Você não pode ter um mapa hash com várias chaves, mas pode ter um objeto que recebe vários parâmetros como chave.
Crie um objeto chamado Índice que assume um valor x e y.
Então tenha o seu
HashMap<Index, Value>
para obter o seu resultado. :)fonte
hashCode
eequals
.Implementado em coleções comuns MultiKeyMap
fonte
Duas possibilidades. Use uma chave combinada:
Ou um mapa do mapa:
fonte
hashCode
eequals
métodos.Use a
Pair
como teclas paraHashMap
. O JDK não tem par, mas você pode usar uma biblioteca de terceiros, como http://commons.apache.org/lang, ou escrever um par de seus próprios.fonte
Crie uma classe de valor que representará sua chave composta, como:
tomando cuidado para substituir
equals()
ehashCode()
corretamente. Se isso parecer muito trabalhoso, você pode considerar alguns contêineres genéricos prontos, comoPair
fornecidos pelo apache commons, entre outros.Também há muitas perguntas semelhantes aqui, com outras ideias, como usar a Tabela de Guava , embora permita que as chaves tenham tipos diferentes, o que pode ser um exagero (no uso de memória e complexidade) no seu caso, pois entendo que suas chaves são inteiras.
fonte
Se forem dois inteiros, você pode tentar um truque rápido e sujo:
Map<String, ?>
usar a tecla comoi+"#"+j
.Se a chave
i+"#"+j
for a mesma quej+"#"+i
tentemin(i,j)+"#"+max(i,j)
.fonte
String
com consequências hilárias.i#j = j#i
, quandoi == j
isso usando omin/max
truque não vai fazer.5#5
e5#5
trocados?5#3
ter o mesmo hash3#5
, então você usa min / max para fazer cumprir3#5
esta ordem.Você também pode usar a implementação da tabela goiaba para isso.
Tabela representa um mapa especial onde duas chaves podem ser especificadas de forma combinada para se referir a um único valor. É semelhante a criar um mapa de mapas.
fonte
Você poderia criar seu objeto-chave da seguinte forma:
public class MapKey {
}
A vantagem disso é: sempre garantirá que você esteja cobrindo todos os cenários de iguais.
NOTA : Seu key1 e key2 devem ser imutáveis. Só então você será capaz de construir um objeto de chave estável.
fonte
podemos criar uma classe para passar mais de uma chave ou valor e o objeto desta classe pode ser usado como um parâmetro no mapa.
fonte
Você pode baixá-lo no link abaixo: https://github.com/VVS279/DoubleKeyHashMap/blob/master/src/com/virtualMark/doubleKeyHashMap/DoubleKeyHashMap.java
https://github.com/VVS279/DoubleKeyHashMap
Você pode usar chave dupla: hashmap de valor,
fonte