
🔹 Introdução
Quem programa em Java cedo ou tarde se depara com os métodos equals e hashCode em Java. Embora pareçam simples, uma implementação incorreta desses métodos pode causar bugs silenciosos, especialmente ao usar coleções como HashMap e HashSet.
Neste artigo, você aprenderá em profundidade como funcionam o equals e o hashCode, quais são seus contratos, erros clássicos que até bibliotecas do Java já cometeram e as boas práticas recomendadas por Joshua Bloch no Java Efetivo.
📌 O que é o método equals em Java?
O método equals define quando dois objetos são logicamente iguais, independentemente de serem a mesma instância na memória.
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof MinhaClasse)) return false;
MinhaClasse other = (MinhaClasse) o;
return campo1.equals(other.campo1)
&& campo2 == other.campo2;
}
Diferença entre == e equals
==→ compara referênciasequals→ compara valores lógicos
📜 O contrato do equals (as 5 regras)
Toda implementação correta de equals deve respeitar:
- Reflexividade
x.equals(x)deve sertrue. - Simetria
Sex.equals(y)étrue, entãoy.equals(x)também deve ser. - Transitividade
Sex.equals(y)ey.equals(z), entãox.equals(z). - Consistência
Chamadas repetidas retornam o mesmo resultado se o estado não mudar. - Não nulidade
x.equals(null)deve retornarfalse.
🚫 Um erro clássico: herança e equals
Um dos erros mais perigosos é estender uma classe instanciável e adicionar campos de valor.
Exemplo problemático:
class ColorPoint extends Point {
private final Color color;
}
Esse padrão viola simetria ou transitividade, dependendo da implementação.
✔️ Solução correta: prefira composição
class ColorPoint {
private final Point point;
private final Color color;
}
Essa abordagem preserva o contrato do equals e segue o princípio de substituição de Liskov.
📌 Quando NÃO sobrescrever equals
Você não deve sobrescrever equals se:
- cada instância é única (ex:
Thread) - a superclasse já implementa corretamente
- não há conceito de igualdade lógica
- a classe é
enum
🔑 O que é o método hashCode em Java?
O método hashCode retorna um número inteiro usado por estruturas baseadas em hash.
Exemplos:
HashMapHashSetHashtable
📜 O contrato do hashCode
- O valor deve ser consistente durante a execução
- Objetos iguais pelo
equalsdevem ter o mesmo hashCode - Objetos diferentes idealmente devem ter hashCodes diferentes
❌ O bug silencioso mais comum
Sobrescrever equals sem sobrescrever hashCode:
Map<PhoneNumber, String> map = new HashMap<>();
map.put(new PhoneNumber(707, 867, 5309), "Jenny");
map.get(new PhoneNumber(707, 867, 5309)); // retorna null 😱
Isso acontece porque o HashMap usa o hashCode antes do equals.
🚫 Pior implementação possível de hashCode
@Override
public int hashCode() {
return 42;
}
✔️ Cumpre o contrato
❌ Destrói o desempenho (O(n²))
✅ Receita correta para hashCode (Joshua Bloch)
@Override
public int hashCode() {
int result = Short.hashCode(areaCode);
result = 31 * result + Short.hashCode(prefix);
result = 31 * result + Short.hashCode(lineNum);
return result;
}
Por que usar 31?
- número primo
- boa distribuição
- otimização automática pela JVM
⚠️ Nunca exclua campos significativos do hashCode
Isso não é teórico.
Antes do Java 2, o String.hashCode() usava apenas 16 caracteres da string.
Para URLs, isso causava colisões massivas e degradação severa de desempenho.
👉 Resultado: tabelas hash inutilizáveis.
📌 Não especifique o valor do hashCode na documentação
Evite algo como:
“hashCode retorna 31 * a + b”
Se você fizer isso:
- clientes passam a depender
- você perde liberdade de evolução
- erros ficam eternos
👉 hashCode é detalhe de implementação, não contrato público.
🤖 AutoValue, records e IDEs
Hoje você não precisa escrever isso na mão:
record(Java moderno)- AutoValue (Google)
- Geração automática pela IDE
Essas opções:
- evitam erros
- mantêm consistência
- reduzem código boilerplate
✅ Checklist final (salve isso)
- Sobrescreveu
equals? → sobrescrevahashCode - Usam os mesmos campos?
- Classe é imutável?
- Evitou herança problemática?
- Não excluiu campos “para otimizar”?
- Não documentou o algoritmo do hash?
🎯 Conclusão
Os métodos equals e hashCode em Java não são detalhes — eles sustentam o funcionamento correto das coleções mais usadas da linguagem. Uma implementação errada pode causar bugs difíceis de rastrear e quedas drásticas de desempenho.
Seguindo as boas práticas apresentadas aqui, você escreve código:
- correto
- previsível
- performático
- pronto para evoluir






Deixe um comentário