Como implementar o método hashCode?

2014/10/06

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;
    }
}