Java POO Intermediário
equals e hashCode
Em Java, os métodos equals e hashCode definem como objetos são comparados e armazenados em coleções baseadas em hash, como HashMap e HashSet. O contrato de equals exige reflexividade, simetria, transitividade, consistência e que x.equals(null) seja false. O contrato de hashCode diz que objetos iguais devem ter o mesmo hash, e que o hash deve ser consistente durante a execução.
Quando você sobrescreve equals, deve sobrescrever hashCode. Caso contrário, objetos iguais podem acabar em baldes diferentes, quebrando o funcionamento de HashSet e HashMap. A classe Objects oferece Objects.equals e Objects.hash para facilitar a implementação correta e evitar NullPointerException.
Armadilhas comuns incluem usar == em vez de equals, esquecer de sobrescrever hashCode, usar campos mutáveis como base para o hash e confundir equals com comparação de referências. Entender esses detalhes é essencial para escrever código robusto com coleções.
Pontos-chave
- O contrato de
equalsexige reflexividade, simetria, transitividade, consistência ex.equals(null) == false. - Objetos iguais por
equalsdevem ter o mesmohashCode. HashSeteHashMapusamhashCodepara localizar o balde eequalspara confirmar a igualdade.Objects.equalseObjects.hashsimplificam a implementação e tratamnullcom segurança.- Nunca use campos mutáveis no cálculo de
hashCodese o objeto for chave de coleção.
import java.util.*;
class Pessoa {
private final String nome;
private final int idade;
Pessoa(String nome, int idade) {
this.nome = nome;
this.idade = idade;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Pessoa pessoa = (Pessoa) o;
return idade == pessoa.idade && Objects.equals(nome, pessoa.nome);
}
@Override
public int hashCode() {
return Objects.hash(nome, idade);
}
@Override
public String toString() {
return nome + " (" + idade + ")";
}
}
public class EqualsHashCodeDemo {
public static void main(String[] args) {
Pessoa p1 = new Pessoa("Ana", 30);
Pessoa p2 = new Pessoa("Ana", 30);
System.out.println("p1.equals(p2): " + p1.equals(p2));
System.out.println("p1.hashCode() == p2.hashCode(): " + (p1.hashCode() == p2.hashCode()));
Set<Pessoa> conjunto = new HashSet<>();
conjunto.add(p1);
conjunto.add(p2);
System.out.println("Tamanho do HashSet: " + conjunto.size());
Map<Pessoa, String> mapa = new HashMap<>();
mapa.put(p1, "Primeira");
mapa.put(p2, "Segunda");
System.out.println("Valor no HashMap: " + mapa.get(p1));
}
}