Equals e HashCode em Java: Guia Completo com Exemplos, Erros Comuns e Boas Práticas

Tempo de leitura: 4 min

Escrito por Michel Adriano Medeiros
em 18/01/2026

Equals e HashCode em Java: Guia Completo com Exemplos, Erros Comuns e Boas Práticas

🔹 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ências
  • equals → compara valores lógicos

📜 O contrato do equals (as 5 regras)

Toda implementação correta de equals deve respeitar:

  1. Reflexividade
    x.equals(x) deve ser true.
  2. Simetria
    Se x.equals(y) é true, então y.equals(x) também deve ser.
  3. Transitividade
    Se x.equals(y) e y.equals(z), então x.equals(z).
  4. Consistência
    Chamadas repetidas retornam o mesmo resultado se o estado não mudar.
  5. Não nulidade
    x.equals(null) deve retornar false.

🚫 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:

  • HashMap
  • HashSet
  • Hashtable

📜 O contrato do hashCode

  1. O valor deve ser consistente durante a execução
  2. Objetos iguais pelo equals devem ter o mesmo hashCode
  3. 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? → sobrescreva hashCode
  • 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

Você vai gostar também:

Para enviar seu comentário, preencha os campos abaixo:

Deixe um comentário


*


*


Seja o primeiro a comentar!

Damos valor à sua privacidade

Nós e os nossos parceiros armazenamos ou acedemos a informações dos dispositivos, tais como cookies, e processamos dados pessoais, tais como identificadores exclusivos e informações padrão enviadas pelos dispositivos, para as finalidades descritas abaixo. Poderá clicar para consentir o processamento por nossa parte e pela parte dos nossos parceiros para tais finalidades. Em alternativa, poderá clicar para recusar o consentimento, ou aceder a informações mais pormenorizadas e alterar as suas preferências antes de dar consentimento. As suas preferências serão aplicadas apenas a este website.

Cookies estritamente necessários

Estes cookies são necessários para que o website funcione e não podem ser desligados nos nossos sistemas. Normalmente, eles só são configurados em resposta a ações levadas a cabo por si e que correspondem a uma solicitação de serviços, tais como definir as suas preferências de privacidade, iniciar sessão ou preencher formulários. Pode configurar o seu navegador para bloquear ou alertá-lo(a) sobre esses cookies, mas algumas partes do website não funcionarão. Estes cookies não armazenam qualquer informação pessoal identificável.

Cookies de desempenho

Estes cookies permitem-nos contar visitas e fontes de tráfego, para que possamos medir e melhorar o desempenho do nosso website. Eles ajudam-nos a saber quais são as páginas mais e menos populares e a ver como os visitantes se movimentam pelo website. Todas as informações recolhidas por estes cookies são agregadas e, por conseguinte, anónimas. Se não permitir estes cookies, não saberemos quando visitou o nosso site.

Cookies de funcionalidade

Estes cookies permitem que o site forneça uma funcionalidade e personalização melhoradas. Podem ser estabelecidos por nós ou por fornecedores externos cujos serviços adicionámos às nossas páginas. Se não permitir estes cookies algumas destas funcionalidades, ou mesmo todas, podem não atuar corretamente.

Cookies de publicidade

Estes cookies podem ser estabelecidos através do nosso site pelos nossos parceiros de publicidade. Podem ser usados por essas empresas para construir um perfil sobre os seus interesses e mostrar-lhe anúncios relevantes em outros websites. Eles não armazenam diretamente informações pessoais, mas são baseados na identificação exclusiva do seu navegador e dispositivo de internet. Se não permitir estes cookies, terá menos publicidade direcionada.

Visite as nossas páginas de Políticas de privacidade e Termos e condições.

Importante: Este site faz uso de cookies que podem conter informações de rastreamento sobre os visitantes.
Criado por WP RGPD Pro