-
se uma classe sobrescreve o equals, ela deve sobrescrever o hashCode também;
-
se ambos são sobrescritos, equals e hashCode devem usar o mesmo conjunto de campos;
-
se o equals entre dois objetos é true, o hashCode desses objetos deve ser o mesmo;
-
se o objeto for imutável, então o hashCode é candidato para cache e lazy initialization;
Já ouvi muitos desenvolvedores Java pouco experientes afirmarem que o hashCode obtém um identificador único (unique id) do objeto. É importante salientar que isso não é verdade, o hashCode não é um identificador único!
Abaixo temos um exemplo padrão de implementação do método hashCode que leva em consideração cada atributo, este código é análogo aos algoritmos gerados pelas IDE's eclipse e NetBeans.
import java.util.Arrays;
class MinhaClasse {
private int atributo1;
private Object atributo2;
private String[] atributo3;
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + atributo1;
result = prime * result + ((atributo2 == null) ? 0 : atributo2.hashCode());
result = prime * result + Arrays.hashCode(atributo3);
return result;
}
}
Percebam que o código exige bastante atenção quando for realizado uma manutenção, principalmente se a classe for alterada para possuir mais atributos que possam influenciar na computação do hashCode.
Tendo em vista as peculiaridades na acerca do método hashCode, disponibilizei em meu repositório a classe HashCodeUtils que simplifica a implementação do método hashCode.
Abaixo, exemplos práticos de como utilizar a classe HashCodeUtils para implementar o método hashCode:
Primeiro um exemplo de método hashCode que utiliza somente um atributo:
import static br.com.staroski.equality.HashCodeUtils.*;
class MinhaClasse {
private int atributo;
public int hashCode(){
return hash(SINGLE_VALUE, atributo);
}
}
Agora um exemplo de método hashCode que utiliza contribuição de vários atributos:
import static br.com.staroski.equality.HashCodeUtils.*;
class MinhaClasse {
private int atributo1;
private Object atributo2;
private String[] atributo3;
public int hashCode(){
int hash = MULTI_VALUE;
hash = hash(hash, atributo1);
hash = hash(hash, atributo2);
hash = hash(hash, atributo3);
return hash;
}
}