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” ??
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:
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.
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.
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
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
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?!
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 ??
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