Duvida em hashcode e equals

Pessoal eu to com duvida como o metado hashcode trabalha alguem poderia me ajudar a entender melhor o metodo hashcode e o metodo equals…
2ª Duvida porque não correto usar uma variavel transiente no metodo hashcode()…?

[quote=Raff]Pessoal eu to com duvida como o metado hashcode trabalha alguem poderia me ajudar a entender melhor o metodo hashcode e o metodo equals…
2ª Duvida porque não correto usar uma variavel transiente no metodo hashcode()…?
[/quote]

O método equals testa se o objeto é igual a outro.
O hashCode retorna um inteiro que segue a regra : Se A.equals(B) então A.hashCode()==B.hashCode()
Ambos usam variáveis de estado para saber o que retornar. Isso responde à 2 pergunta.

hashcode é um metodo de Object que tem por finalidade atribuir um “unico” codigo a uma classe… qdo vc vai usar uma collection map as que precisam de chave e valor caso vc use uma classe C vc tera que sobrescrever o metodo hashCode da sua classe C para que cada objeto da sua classe c retorne um hashCode diferente pois assim vc vai garantir que cada objeto c colocado para uma chave tenha vinculado a ele apenas um valor que sera o ideal… ja o metodo equals é um metodo tbm de Object que serve para vc poder comparar o valor de 2 objetos ou seja quando 2 objetos carro por exemplo sao iguais? se vc tiver uma classe carro com um atributo placa pode sobscrever equals que vai receber como parametro outro objeto que sera feito o cast para o objeto carro dentro do metodo e la vc vai comparar se o atributo placa de ambos são iguais se forem retornaram true senão false…

vc não pode usar variaves trasientes no hasCode pq como vc deve saber variaveis trasientes não são serializaveis e caso vc use como “codigo” no seu hascode apos serializadas e depois deserializadas a variavel transiente não voltara com o valor atribuido a ela antes da serialização e sim um valor defult o que vai ocasionar supondo q sua variavel for um int sempre o valor 0 então caso vc use um transient como hash code todos os objetos terao o mesmo hascode o valor default da variavel…

bom vamos la…
o metodo hashCode é ideal quando vc vai trabalhar com conjunto(HashSet, HashMap etc) pq? Devido quando vc quiser retirar algo desse conjunto… para ter certeza que vai tirar a coisa certa… se vc deixar a implemetação do hashCode por conta da jvm vc vai ter dois objetos que pode ser true - pelo metodo equals porem tem codigos hashCode mesmo assim eles sao adicionados ao seu conjunto do tipo HashSet por exemplo.
a implementação é simples:

int hashCode(){
return 10;
}

o codigo acima é valido porem nao é eficiente ja que ele sempre retornar o mesmo valor para o codigo hashing entao… vc deve implementar seu hashCode de maneira eficiente para o objeto tipo:

int hashCode(){
return i*10;
}

Vamos dizer no exemplo acima que o codigo hashing será o valor que i receber * 10 é uma maneira mais eficiente que a primeira que citei… mais a implementacao fica de acordo com o seu programa vai fazer…

transient - nao é recomendavel usar o modificador transient pq quando vc des-serializar um objeto o valor desse objeto será seu valor padrao se for primitivo será 0 se for um objeto sera null. Entao vc vai cair na questao do codigo hashing do primeiro exemplo que dei… de sempre retornar o mesmo valor para todos os codigos hashing.
olha um problema abaixo de ter uma má implementação do hashing.

public class Difhas {
String nome;
	Difhas(String name){
	nome=name;
	}
	public boolean equals(Object o){
		if((o instanceof Difhas)&&(((Difhas)o).nome==this.nome)){
			return true;
		}else{return false;}
	}
	public int hashCode(){
		return nome.length()*2;
	}
	
	public static void main(String[] args) {
		Difhas d = new Difhas("cam");
		Difhas d1 = new Difhas("cay");
		System.out.println(d.equals(d1));
	System.out.println(d.hashCode());
	System.out.println(d1.hashCode());
	}}
/*objeto diferente porem hashing iguais*/

agora analisa esse codigo

class EffectCode{	
	public static void main(String arg[]){
		Car c = new Car(101);
		Car c1 = new Car(101);		
		
	System.out.println(c.equals(c1));
	System.out.println(c.hashCode());
	System.out.println(c1.hashCode());
	}
}

class Car{
 int placa;
	Car(int p){ placa=p;}
	public boolean equals(Object o){
		if((o instanceof Car) &&(((Car)o).placa==this.placa)){
			return true;
		}else{return false;}
	}
	public int hashCode(){
	return placa*2/3;	
	}
}
/* lembrar que o equals deve ser da class q desejo comparar*/
/* 
/* objeto(valores) iguais e hashing ==*/

Então a RECOMENDAÇÃO é: se seu equals for true o codigo hashing deve ser igual, se for diferente deve ser diferente, mas se deixar igual não problemas se compilação, ou exceção, mais vc vai ter problemas na hora que trabalhar com conjuntos.

o metodo equals- serve para comparar valores.

obs as classes String e Wrapper ja implementa tanto o equals quanto o metodo hashCode por padrão.

exemplo com tudo que falei:

public class HashInt {
	String aa;
HashInt(String a){
	aa=a;
}
	public static void main(String[] args) {
		Integer a=20;
		Integer b=20;
		
		String n = "Camilo";
		String n1 = "Camilo";
		
		HashInt h = new HashInt("Camilo");
		HashInt h1 = new HashInt("Camilo");
			
System.out.println(a.equals(b));//1

System.out.println(n.equals(n1)+ " " + n.hashCode() + " " + n1.hashCode());//2
//objetos = = com hashing !=
System.out.println(h.equals(h1)+ "" + h.hashCode()+""+ h1.hashCode());//3
	}

	public boolean equals(Object o){
		if((o instanceof HashInt)&&(((HashInt)o).aa==this.aa)){
			return true;
		}else{return false;}	}}

/* observe aqui que tenho um equal true porem hashing diferente(//3) isso 
 pq nao implementei meu metodo hashCode entao a jvm nao tem como fazer
 isso ela gera um codigo qualquer*/

resultado do codigo acima

true //1
true 2011086237 2011086237 //2
true 3541984 4565111 //3

flw… espero ter ajudado qualquer duvida so gritar!

Valew pessoal

qualquer duvida eu vou gritar sim :smiley:

Legal Camilo só não entendi uma coisa no seu codigo que eu vou citar a baixo…

[code]
public class Difhas {
String nome;
Difhas(String name){
nome=name;
}
public boolean equals(Object o){
if((o instanceof Difhas)&&(((Difhas)o).nome==this.nome)){//analizar aqui camilo
return true;
}else{return false;}
}
public int hashCode(){
return nome.length()*2;
}

public static void main(String[] args) {
	Difhas d = new Difhas("cam");
	Difhas d1 = new Difhas("cay");
	System.out.println(d.equals(d1));
System.out.println(d.hashCode());
System.out.println(d1.hashCode());
}}

/objeto diferente porem hashing iguais/[/code]

quando eu quero compar se String são iguais eu não devo chamar o metodo equals() já que como você disse a classe String já sobrescreve. Mas ao contrario você não chamo o metodo equas() só comparo “referencia” ou eu estou enganado ou você ??
Me explica isso ai cara falow !!

Camilo eu acho que você estava certo a String já se encontra no Pool né ou nãow

isso String implementa ja op equals… mais vc está se atrapalhando… ali eu to testado o valor do objeto do tipo:Difhas e nao do tipo String… por isso que tenho que implementar o equals… para poder saber se duas instancia da classe Difhas sao equivalentes segundo o metodo equals…

String s = new String("guj");
String s2 = new String("guj");

aqui nem preciso implementar equals ja que a class String ja faz isso…

Difhas d = new Difhas("java");
Difhas d2 = new Difhas("java");

se nao implementar equals… e usar:

d.equals(d2);

retorna false.

era essa sua duvida?

não camilo eu sei sobre isso que a String já implementa o metodo equals eu quis disser que para mim comparar se uma String é igual a outra eu não devo fazer isso exemplo…[code]

String a = “rafael”;
String b = “rafael”;//agora eu quero comparar a String se as String são iguais.

if(a == b){

System.out.println("Assim eles apontam para o mesmo Objecto, não quer dizer que seus conteudos sejam iguais… ");
}

[/code]

agora quando voce fez o método equals() na classe Dfilhas… você fez assim…


public boolean equals(Object o){   
        if((o instanceof Difhas)&&(((Difhas)o).nome==this.nome)){//analizar aqui camilo   
            return true;   
        }else{return false;}   

AGORA ONDE ENTRA A MINHA DÚVIDA… O CÓDIGO NÃO TERIA DE SER ASSIM…

public boolean equals(Object o ){
      
    if(o instanceof Dfilhas) &&(((Dfilhas)o).nome.equals(this.nome)){

    return true;
}
else return false;

}

É essa a minha dúvida colega se você puder responder agradeço !!!

Vc tem razão. Tem que usar equals() , mesmo para String, vc pode fazer simplesmente:

public boolean equals(Object o ){
    return (o instanceof Dfilhas) && (((Dfilhas)o).nome.equals(this.nome));
}

tem certeza que dessa forma o codigo compila… olhe se o uso do if ta correto dessa forma que vc fez… ?
se vc tirar ( ) o codigo está errado… ai que entra a essencia de saber diferenciar cada ( ) va olhando um a um e veja o que a instrução está fazendo… nesse seu caso eu nao tenho uma instrução if correta… no meu caso… testo todo o bloco dentro do if.

Definitivamente a melhor referência sobre equals e hashcode (e alguns detalhes que podem realmente te pegar desprevenido) estão no capítulo 3 do livro Effective Java. Por sinal, esse capítulo está disponível online, no site do autor:

http://developer.java.sun.com/developer/Books/effectivejava/Chapter3.pdf

Não deixe de ler. Aliás, se possível, procure ler o livro todo. É um “must have” para todo programador Java.

[quote=ViniGodoy]Definitivamente a melhor referência sobre equals e hashcode (e alguns detalhes que podem realmente te pegar desprevenido) estão no capítulo 3 do livro Effective Java. Por sinal, esse capítulo está disponível online, no site do autor:

http://developer.java.sun.com/developer/Books/effectivejava/Chapter3.pdf

Não deixe de ler. Aliás, se possível, procure ler o livro todo. É um “must have” para todo programador Java.[/quote]

boa vinny eu aprendi… lendo esse cap 3… show de bola… effective java… :D!

Pessoal Valew ai agora eu aprendi :smiley: auahuauh