Qual é a vantagem de sobrescrever o método hasCode

Olá !!!

Eu andei estudando um pouco sobre hasCode e, até agora, não entendei qual é a vantagem de reescrever esse método.

Eu peguei o seguinte trecho do simulado do site da Caelum e não entendi nada


class Prova{
String nome;
Prova(String nome) {this.nome = nome;}
public int hashCode() {return 0;}
public boolean equals(Object o) {return true;}
}

class Pai {
public static void main(String … args) {
Set<Prova> set = new HashSet<Prova>();
set.add(new Prova(“SCJP”));
set.add(new Prova(“SCJD”));
set.add(new Prova(“SCJP”));
System.out.println(set.size());
}
}

Por que é imprimido “1” quando existe o método hasCode e quando eu tiro o método o valor exibido é “3” ??

Obrigado pela atenção

sabe ler um pouco de ingles?

Ou seja, serve para ajudar em buscas que usam uma tabela hash (Map’s, Set’s, etc)

No seu codigo ele retorna size 1 porque de acordo com hashCode e equals os 3 objetos sao iguais, e em um Set nao existe objeto igual.

Para tabelas hash o numero hashcode vai servir como se fosse um indexador, mais ou menos assim

usuario:
luiz hashcode 1
lubs hashcode 1
joao hashcode 2
pedro hashcode 3

armazenado no set vai estar:
index 1: luiz e lubs
index 2: joao
index 3: pedro

Quando eu for buscar o luiz no Set, ele vai verificar qual eh o hashcode de luiz e ir direto no index dele (no caso 1). Luiz e lubs estao “juntos”, pensa como se tivessem no mesmo saco (o saco de index 1), mas um naum substitui o outro porque o metodo equals deles eh diferente, se equals fosse igual (como eh seu caso, luiz eh igual a lubs), ai naum teria luiz e lubs, apenas um deles.

Alterando e testando seu programa:

  1. altera o retorno de equals para: “return nome.equals(((Prova)o).nome);”. Vai aparecer size 2, dentro do Set os objetos estarao armazenados assim:
    index 0: SCJP, SCJD

Porque size 2? porque o primeiro SCJP tem hashcode e equals igual ao ultimo SCJP, logo soh vai haver um.

  1. altera o retorno de equals para: “return false”. Vai aparecer size 3, dentro do seu Set os objetos estarao armazenados assim:
    index 0: SCJP, SCJD, SCJP

Porque embora eles tenham mesmo hashcode, eles nunca saum iguals (metodo equals), entao saum todos adicionados no mesmo saco, mas nenhum substitui o outro.

  1. altera o retorno de equals para: “return true;” e hashcode para: “return nome.hashCode()”. Vai aparecer size 2, seus objetos sempre saum iguais, mas quando o set for procurar o saco para incluir cada um, o saco do SCJP e do SCJD vaum ser diferentes, ja o saco do primeiro SCJP e do ultimo serao iguais, pois a string SCJP tem o mesmo hashcode. O set vai estar assim:
    index 0: SCJP
    index 1: SCJD

  2. altera o retorno de equals para: “return false;” e hashcode para: “return nome.hashCode();”, vai aparecer 3, pois mesmo tendo o mesmo hashcode, SCJP do primeiro eh diferente (no equals) do SCJP do ultimo. O set vai estar assim:
    index 0: SCJP, SCJP
    index 1: SCJD

  3. altera o retorno de equals para o que vc quizer, adiciona o atributo estatic na classe Prova: “static int i = 0;” e retorna no hashcode: “return i++;”. Agora vc criou uma zona, vai retornar 3, o objeto nem tem um hashcode certo, logo nem buscar dentro do set vc vai conseguir porque naum sera possivel determinar o “saco” que ele esta incluido, ja que o hashCode sempre retorna um numero diferente… a sintaxe disso eh certa, mas a implementacao errada, naum sigo o contrado que deve ser seguido na implementacao do hashcode. Entao sempre que for adicionar em uma tabela hash ele vai adicionar em um outro saco, idependente do equals, logo vai te retornar tamanho 3 e seu set tera:
    index 0: SCJP
    index 1: SCJD
    index 2: SCJP

E quando eu for buscar por exemplo o SCJD, ele vai pensar que esta no saco 3 (isso se buscar logo depois de adicionar o ultimo), como naum existe saco 3, naum vai achar.

Eh mais ou menos assim que funciona e para isso que serve o hashCode. Uma ma implementacao dele ou do equals pode ferrar bastante coisa, entao eh bom sempre ler os “contratos” que devem ser seguidos ao implementa-los. Deu para entender melhor ou confundiu mais?!

deixa eu ver se entendi

Se o valor de retorno do método hashCode for igual, por exemplo, para dois objetos, eu terei que utilizar o método equals como critério de desempate ??

é mais ou menos isso ??

nao, o equals naum serve de ‘desempate’ para o hashcode… o equals serve para ver se dois objetos saum iguais

vc leu a documentacao dos dois metodos?

http://java.sun.com./j2se/1.5.0/docs/api/java/lang/Object.html#hashCode()
http://java.sun.com./j2se/1.5.0/docs/api/java/lang/Object.html#equals(java.lang.Object)

O hashcode eh um numero hash usado para “otimizar” o uso do objeto em tabelas hash, e ai existem uma serie de regras para implementar, como por exemplo:

se equals entre dois objetos retorna true, hashcode desses dois objetos deve retornar o mesmo numero.

se equals retorna false, naum obrigatoriamente hashcode vai retornar valores distintos.

tem que sempre retornar o mesmo valor caso chamado para o memso objeto e que os atributos usados para o equals naum mudarem

Eh soh ler a documentacao…