Problema incomum com hashset

Ola pessoal…

Quando criamos o seguinte tipo de codigo:
Integer i1 = new Integer(1);
Integer i2 = new Integer(1);

...println(i1.equals(i2));

e

HashSet h1 = new HashSet();
h1.add(i1);
h1.add(i2);

Obtemos como resultado true no println e no segundo trecho obtem-se um hashset com um elemento.

Os resultados são bem evidentes em função da maneira como a classe Integer trata o equals e a classe HashSet trata o add.

Porem se eu tiver as classes Objeto1, Objeto2 e Objeto3 como segue, verão que teremos problemas com o hashset, porque este irá adicionar os objetos que devem ser iguais.


class Objeto1 {    
    public Objeto2 o2;
    public Objeto3 o3;
    
    public boolean equals(Object o) {
        if ( (((Objeto1)o).o2).equals(o2) && (((Objeto1)o).o3).equals(o3) )  {
            return true;
        }
        return false;
    }
}

class Objeto2 {
    public int id;
    
    public Objeto2(int i) {
        id = i;
    }
    
    public boolean equals(Object o) {
        if ( ((Objeto2)o).id == this.id) {
            return true;
        }
        return false;
    }
}

class Objeto3 {
    public int id;
    
    public Objeto3(int i)  {
        id = i;
    }
    
    public boolean equals(Object o) {
        if ( ((Objeto3)o).id == this.id) {
            return true;
        }
        return false;
    }
}

class TestObjetos {
     main( ... args[]) {

        Objeto1 o1 = new Objeto1();
        o1.o2 = new Objeto2(1);
        o1.o3 = new Objeto3(1);
        
        Objeto1 o2 = new Objeto1();
        o2.o2 = new Objeto2(1);
        o2.o3 = new Objeto3(1);
        
        System.out.println(o1.equals(o2));   <-- aqui ok
        
        HashSet h = new HashSet();
        h.add(o1);
        h.add(o2);   <-- ira aceitar esse objeto... não quero que aceite.
     }

}

Só pra lembrar: A classe HashSet não aceita um novo elemento se este já existir (comparação feita atraves do metodo equals).

Obrigado.

Um hashset usa “hashCode”, depois é que usa “equals”. Você não sobreescreveu o método “hashCode”. A implementação default de hashCode é a de Object, que retorna valores diferentes para objetos diferentes (mesmo que as suas variáveis de instância tenham valores iguais.)

Dica: Leia o Effective Java - lá o sr. Joshua Bloch manda você repetir 7 vezes por dia, de preferência ajoelhado e na direção de onde o sr. James Gosling estiver: “Quando implementar equals, implemente hashCode e vice-versa.”

Dica 2: Um “hashset” não tem esse nome à toa. Você deveria ter desconfiado.

foi mal… eu esqueci completamente disso… no livro da katy tb tem essa questão MUITO bem abortada…
falhei…