Dúvida sobre HashSet e LinkedHashSet

Olá Pessoal,

Estou estudando para SCJP e resolvendo algumas questões me deparei com a seguinte situação, onde um HashSet ou LinkedHashSet não considera igual dois objetos que sobrescrevem devidamente o método equals mas não sobrescrevem hashcode. Até onde sei o fator determinande para que dois objetos sejam considerados iguais é que a o método equals seja devidamente sobrescrito e implementado.

Pesquisando no livro da K.Sierra encontrei isso:

[quote]A Set cares about uniqueness?it doesn’t allow duplicates. Your good friend the
equals() method determines whether two objects are identical (in which case only
one can be in the set). The three Set implementations are described in the following
sections.[/quote]

Fazendo testes comprovei que HashSet e LinkedHashSet realmente precisam da implementação do equals e do hashcode em conjunto para poder determinar que dois objetos são iguais. Eu gostaria de saber se é isso mesmo e o porque?

package br.com.jbjares.scjp.collections;

import java.util.HashSet;
import java.util.Set;

	public class Person{
		private String name;
		
		 public Person(String name) {
		 this.name = name;
		 } 

		@Override
		public boolean equals(Object obj) {
			if (this == obj)
				return true;
			if (obj == null)
				return false;
			if (getClass() != obj.getClass())
				return false;
			Person other = (Person) obj;
			if (name == null) {
				if (other.name != null)
					return false;
			} else if (!name.equals(other.name))
				return false;
			return true;
		}

		public static void main(String[] args) {
			
			 Set hashSet = new HashSet();
			 System.out.println(hashSet.add(new Person("joao")));
			 System.out.println(hashSet.add(new Person("joao")));
			 System.out.println(hashSet.add(new Person("joao")));
			 
			 for(Object o:hashSet){
				System.out.println(o); 
			 }
			 
			 
		}

}



RESULTADO:
true
true
true
br.com.jbjares.scjp.collections.Person@addbf1
br.com.jbjares.scjp.collections.Person@19821f
br.com.jbjares.scjp.collections.Person@3e25a5

Apenas o equals pode determinar se dois objetos são iguais, porem o hashCode tem o papel de exclusão, para que 2 objetos sejam iguais, eles precisam ter o mesmo hashCode, porem nem todos objetos de mesmo hashCode são iguais…

portanto o hashCode é usado para excluir… se 2 objetos tem hashCode diferente, não precisa nem testar o equals, e já se pode descartar o objeto, portanto é extremamente aconselhavel, ao sobrescrever equals, o faze-lo em hashCode…

algumas collection, usam este atalho de hashCode, para otimizar o código…

algo mais ou menos assim

if ( one.hashCode() != other.hashCode() ) return false; return one.equals(other); isso otimiza quando os objetos são diferente, pois o teste de hashCode, via int é bem rapido… e por isso pode dar problemas na hora de usar contains, remove, removeAll, retainsAll em uma collection, pois ele pode usar o atalho do hashCode para excluir a igualdade…

posso te aconselhar essa leitura aki sobre collections, Coleções: como não usar arrays tem comentando la sobre esse fato do hashCode, e da importancia de sobrescrever os 2, inclusive algumas IDEs como o netbeans, dão Warning avisando para sobrescrever hashCode, quando vc o sobrecreve equals

apesar do titulo ser voltado para não usar array, o link é super bem explicativo, e fala disso de hashCode e equals…

Caro Lavieri,

Nota 10 sua explicação e o material indicado. Agora sim, deu pra fechar legal a compreenção a respeito do equals e do hashcode. Muito Obrigado!