[Dúvida] Sobrepor HashCode

11 respostas
InsaneChess

Prezados, bom dia.
Estou estudando sobre coleções. No caso abaixo é sobre a HashSet.
Para dois objetos serem considerados iguais o livro fala para sobrepor equals() e HashCode() para eles terem o mesmo código de Hashing.
OK, eu intendi a parte de sobrepor equals, porém não intendi a sobreposição de hashing.

Alguem pode me explicar o que o método abaixo hashCode sobreposto faz?
Outra coisa, Hashing é o endereço que o objeto é armazenado na memória? sendo assim, dois objetos com o mesmo hashing, um deles é descartado ou tem como os dois ocuparem o mesmo lugar?

Obrigado, desculpem o incomodo.
Uma ótima semana para todos.

public class Song implements Comparable<Song>{
        String title;
        String musica;
        public Song(String t, String m){
            title = t;
            musica = m;
        }
        
        public String gettitle(){
            return title;
        }
        public String getmusica(){
            return musica;
        }
        
        public String toString(){
            return title;
        }

        
        public int compareTo(Song s) {
            return title.compareTo(s.gettitle());    
        }    
        
        public boolean equals(Song s){
            return gettitle().equals(s.gettitle());
        }
        
        public int hashCode(){
            return title.hashCode();
        }
    }

11 Respostas

thiago.correa

Não, o hashCode é um código em que é gerado a partir do estado do objeto, não tem nada a ver com endereço de memória (lembre-se, java != c/c++)

Ou seja, se dois objetos ao ser comparado através do equals, o seu hashCode deve ser igual! Quanto melhor for o seu algorimo de hashCode, mais rápido seu obejto será localizado no HashSet

evertonsilvagomesjav

E se o equals retornar false?

ViniGodoy

Para ver como gerar um hashCode, veja o post abaixo:
http://www.guj.com.br/posts/list/52485.java#276120

O importante é que sejam usados os mesmos campos que foram usados para gerar o equals.

Aqui tem um exemplo de classe que já usa esse algorítmo:
http://www.guj.com.br/posts/list/101275.java#546125

É o mesmo usado no “generate hashcode” da maior das IDEs Eclipse e Netbeans, sugerido no capítulo 3, item 8, do livro do Joshua Bloch, Effetive Java (recomendo que leia):
http://java.sun.com/developer/Books/effectivejava/Chapter3.pdf

mrrbigu

Se você sobrepor e implementar corretamente os métodos equal e hashcode, e o equals=true, então o hashcode deverá ser idêntico para os dois objetos, porém se o equals=false, ainda assim os objetos poderão ter o mesmo hashcode.

InsaneChess

[purple]OK, irei ler os artigos e futuramente o livro.
Obrigado a todos.

Então quer dizer que o código abaixo faz o estado do objeto ser o mesmo estado da váriavel title?
Digamos, o hashcode da váriavel title será considerado o hashcode do objeto? Todo objeto com a váriavel title repetida ira gerar o mesmo hashcode?
Ta meio confuso rsrs

public int hashCode(){ return title.hashCode(); }

evertonsilvagomesjav

InsaneChess:
[purple]OK, irei ler os artigos e futuramente o livro.
Obrigado a todos.

Então quer dizer que o código abaixo faz o estado do objeto ser o mesmo estado da váriavel title?
Digamos, o hashcode da váriavel title será considerado o hashcode do objeto? Todo objeto com a váriavel title repetida ira gerar o mesmo hashcode?
Ta meio confuso rsrs

public int hashCode(){ return title.hashCode(); }

Não esse caso vc esta retornando o hashCode de sua variavel title so isso.

InsaneChess

Boa noite,
Everton por favor me explica o seguinte.
Se "Não esse caso vc esta retornando o hashCode de sua variavel title so isso. "
Então, como apenas esse retorno irá fazer os outros objetos que tenham a váriavel title com o mesmo nome tambem ter o mesmo hashcode?

evertonsilvagomesjav

InsaneChess:
Boa noite,
Everton por favor me explica o seguinte.
Se "Não esse caso vc esta retornando o hashCode de sua variavel title so isso. "
Então, como apenas esse retorno irá fazer os outros objetos que tenham a váriavel title com o mesmo nome tambem ter o mesmo hashcode?

Cara quem tem o mesmo hashCode é o objeto(variavel) title e não os objetos que tenham a variavel title, entendeu?

ViniGodoy

A regra é simples. Dois objetos que são equals, devem retornar hashCodes iguais.

Note que com essa regra, esse é um hash perfeitamente válido:

public int hashCode() { return 1; }

Não é eficiente, mas é válido.

Agora, para que serve esse hashcode? Uma das coisas que você pode fazer com o hashCode é organizar objetos. Por exemplo, o seu hashCode poderia ser um índice, para um array contendo listas dos seus objetos. Por exemplo:

List<SuaClasse> objetos[] = new List<SuaClasse>()[10];

Para inserir um objeto nessa lista, você faria o seguinte:

public void inserir(SuaClasse objeto) { int hashCode = objeto.hashCode(); int indice = hashCode % objetos.length; if (!objetos[indice].contains(objeto)) objetos[indice].add(objeto); }

Qual a vantagem disso? A vantagem ao invés de uma enorme lista, cheia de objetos, aqui você tem um conjunto de listas muito pequenas, organizadas pelo hash. Portanto, testar se um objeto existe ou não nessa estrutura é muitíssimo rápido. Primeiro, você acha o índice da mini-lista de objetos. Depois, você percorre essa pequena lista, testando se seu objeto já está lá dentro ou não, através do método equals (isso é o que o contains faz).

Agora, a implementação de hashCode que dei ali em cima (retornando sempre 1) não seria eficiente. Isso pq ela sempre retornaria o mesmo índice. Por isso, para que um hashCode funcione bem, deve haver uma pequena chance de colisão, ou seja, para dois objetos diferentes, a chance de que dois hashCodes sejam iguais deveria ser muito pequena. O algoritmo que postei no link tem essa propriedade, com bom custo computacional. Embora não seja o melhor algoritmo de hash existente.

Aquela estrutura que coloquei no exemplo é mais ou menos como a classe HashSet do java funciona. Outras classes como a HashMap também usam esse tipo de estratégia. Note também que o algoritmo quebra, se o hash dos elementos internos mudar uma vez que já estejam na lista.

ViniGodoy

InsaneChess:
Então quer dizer que o código abaixo faz o estado do objeto ser o mesmo estado da váriavel title?
Digamos, o hashcode da váriavel title será considerado o hashcode do objeto? Todo objeto com a váriavel title repetida ira gerar o mesmo hashcode?
Ta meio confuso rsrs

O hashCode não é o estado do objeto. Nem necessariamente uma representação dele.

Veja, a definição do seu objeto diz que, para efeitos de comparação, dois objetos com título iguais são considerados objetos iguais.

Portanto, é natural que o hashCode dele seja baseado no hashCode do título. O hashCode da classe String retorna um número idêntico caso duas Strings sejam iguais, e provavelmente diferentes se duas strings forem diferentes.

É incorreto dizer que o hashCode representa o estado do objeto, pois o conceito de igualdade nem sempre está ligado ao estado. Por exemplo, alguns sistemas consideram iguais objetos que tenham o mesmo id. Entretanto, todos os outros atributos podem estar diferentes, e, por consequência, ambos os objetos terem estados diferentes. Mas eles retornariam true no equals e no hashCode.

InsaneChess

Obrigado ao ViniGodoy e a todos que me ajudaram.
Caso alguem ainda tenha interesse no assunto, segue um link interessante.

http://blog.caelum.com.br/2006/09/04/ensinando-que-e-o-hashcode/

Abraços!!!

Criado 22 de setembro de 2010
Ultima resposta 23 de set. de 2010
Respostas 11
Participantes 5