[RESOLVIDO] Método get da HashMap não chama método equals da classe

11 respostas
T

Galera,
Estou com uma pequena dúvida sobre a utilização de uma HashMap.

Seguinte:
Possuo uma HashMap em que a chave é uma instância de uma classe criada por mim.
Eu sobreescrevi o método equals da classe perfeitamente, e quando chamo o método get da HashMap, o método equals da classe não é chamado.
Eu preciso fazer algo para que isso aconteça?

Qualquer ajuda é bem vinda.

Muito obrigado.

11 Respostas

A

Sim, precisa. Implemente o método hashCode() da sua classe também.

Em linhas gerais, o HashMap vai comparar o hashcode primeiro e depois ver se é igual…

T

Sim, precisa. Implemente o método hashCode() da sua classe também.

Em linhas gerais, o HashMap vai comparar o hashcode primeiro e depois ver se é igual…

Deixa eu ver se entendi.
Se o método hashCode estiver retornando sempre o mesmo valor pra ver se o objeto é igual ele chama o equals. É isso?

A

Sim, precisa. Implemente o método hashCode() da sua classe também.

Em linhas gerais, o HashMap vai comparar o hashcode primeiro e depois ver se é igual…

Deixa eu ver se entendi.
Se o método hashCode estiver retornando sempre o mesmo valor pra ver se o objeto é igual ele chama o equals. É isso?

Exatamente, só tem um outro porém…

Antes dele chamar equals, ele testará com == para verificar se é a mesma instância…

Se a instância for a mesma, ele não chamará equals também…

T

Sim, precisa. Implemente o método hashCode() da sua classe também.

Em linhas gerais, o HashMap vai comparar o hashcode primeiro e depois ver se é igual…

Deixa eu ver se entendi.
Se o método hashCode estiver retornando sempre o mesmo valor pra ver se o objeto é igual ele chama o equals. É isso?

Exatamente, só tem um outro porém…

Antes dele chamar equals, ele testará com == para verificar se é a mesma instância…

Se a instância for a mesma, ele não chamará equals também…

Beleza.
No meu caso a instância não é a mesma.
E mesmo se fosse, sendo a mesma instância não tem mais o que testar. Os objetos são iguais. Certo?

Obrigado pela ajuda.

A

Só mais um comentário, baseado numa observação que você fez:

Não implemente seu hashCode com algo do tipo:

public int hashCode() {
        return 1;
    }

Se não tiver idéia de como gerar, você pode usar o assistente da IDE mesmo.
Hoje em dia qualquer IDE implementa um método “bom o bastante” via assistente.

T

AbelBueno:
Só mais um comentário, baseado numa observação que você fez:

Não implemente seu hashCode com algo do tipo:

public int hashCode() {
        return 1;
    }

Se não tiver idéia de como gerar, você pode usar o assistente da IDE mesmo.
Hoje em dia qualquer IDE implementa um método “bom o bastante” via assistente.

Beleza.
Mas por quê?
Para não correr risco de coincidir com hashCode de outras classes?

ViniGodoy

Se o seu hashcode retornar sempre o mesmo valor, estruturas como os sets deixarão de ser eficientes. Afinal, todos os elementos serão agrupados no mesmo índice, o que elimina o grande granho que essas estruturas dão.

Aqui vai uma dica de como implementar o hashcode corretamente:
http://www.guj.com.br/posts/list/52485.java#276120

O HashSet funciona assim. Imagine que você tem um conjunto de gavetas, onde dentro cabem meias (seus objetos). As gavetas podem ser organizadas de diversas formas. Quem diz que forma você organiza as meias nas gavetas é o hashCode. Você poderia, por exemplo, organizar por cor. Meias azuis na gaveta 1, meias verdes na gaveta 2, meias pretas na gaveta 3.

E assim por diante… Se você quisesse a sua meia amarela da seleção canarinho, você abriria a gaveta das meias amarelas (a gaveta 4) e só precisaria comparar meia a meia (com o equals) até achar a meia amarela da seleção canarinho. Seria mais rápido, pois sua busca se resume apenas as meias amarelas, e não à todas as meias que você tem.

Retornar o mesmo número do hashCode é o mesmo que colocar todas as meias em uma só gaveta.

Diferentes números de hashCodes podem deixar as meias mais ou menos distribuídas nas diversas gavetas. Quanto mais uniformemente distribuídas, mais eficiente será sua procura.

A

tchinfurinfu:
Mas por quê?
Para não correr risco de coincidir com hashCode de outras classes?

Quase isso…
Na verdade um certo número de “colisões” é esperado, mas um grande número pode afetar a performance de coleções baseadas em hash.
(Sendo que, não implementar hashCode, faz com que nem funcionem).

Recomendo a leitura do livro Effective Java 2nd Edition que contém uma boa explicação sobre isso.

EDIT: Estava escrevendo enquanto o ViniGodoy respondeu… uma resposta clara o suficiente, sem precisar do livro…rs

ViniGodoy

Um último complemento. A regra do hashCode diz o seguinte:

“Objetos iguais devem, necessariamente, ter hashCodes iguais”.

Ou seja, se duas meias são amarelas, elas necessariamente devem ter o hashCode 4, da gaveta amarela. Note que ele não diz nada sobre objetos diferentes. Esses, podem ter hashCodes iguais também. Isso só não vai ser tão eficiente (problema seu se quer deixar meias amarelas com vermelhas).

T

Valeu galera pela ajuda.
Vou implementar as mudanças e depois posto aqui dizendo se ficou legal.
Abraço a todos.
E mais uma vez, obrigado.

T

Fala galera.
A implementação do método hashCode funcionou perfeitamente.
Muito obrigado pela ajuda.
Valeu galera.

Criado 6 de outubro de 2010
Ultima resposta 7 de out. de 2010
Respostas 11
Participantes 3