7
votes

Hashset contient la méthode, un comportement étrange

Voici mon code:

public class testGui {



    public static void main(String[] arg){
        class TESTS{
            String t;

            public TESTS(String t){
                this.t = t;
            }

            @Override
            public boolean equals(Object x){
                System.out.println("My method is called...");
                if(x instanceof TESTS){
                    TESTS zzz = (TESTS) x;
                    return zzz.t.compareTo(t)==0;
                }
                else return false;
            }
        }
        HashSet<TESTS> allItems = new HashSet<TESTS>();
        allItems.add(new TESTS("a"));
        allItems.add(new TESTS("a"));
        System.out.println(allItems.contains(new TESTS("a")));
    }

}


0 commentaires

4 Réponses :


13
votes

Lorsque vous remplacez est égal , vous devez également remplacer hashcode . Sinon, des objets égaux auront différents codes de hachage et être considéré comme inégal.

Il est également fortement recommandé de ne pas remplacer seul hashcode . Mais ce n'est pas essentiel, comme des objets inégaux peuvent avoir le même code de hachage.


4 commentaires

Ils ne seront pas considérés comme inégaux. C'est juste que le hashset n'invoque même pas la méthode des égaux, car il ne le fait que pour les hachons de hashcodes menant au même seau. Et il n'existe que le hashcode n'ayant aucun sens, car Hashset appellera toujours des égaux pour des objets ayant les mêmes hashcodes.


@JB, oui, le fait qu'ils conduisent à différents seaux signifie qu'ils sont considérés comme «inégaux» (considérés comme différents objets). Je ne parle pas de la méthode égale lorsque j'utilise ce terme. Je suis également d'accord sur le fait que hashcode est illogique, c'est pourquoi j'ai fortement recommandé de lui contre. Cependant, il ne casse pas le contrat.


Ce serait bien si la documentation Java mentionnait que HashCode est appelée en premier. Je viens d'être brûlé par cette question dans Java 5.


@Aaron, non seulement ce serait bien, je dirais que, à l'heure actuelle, il est correctement documenté, et cela a persisté jusqu'au Java d'actualité. Il dit que la contient et les méthodes d'ajout sont équivalentes à des objets.equaux, mais ils ne sont manifestement pas.



3
votes

Vous devez également implémenter hashcode , de sorte qu'il soit cohérent avec égale . hashset utilise la méthode HashCode pour décider du compartiment à mettre un élément dans, et appelle égale uniquement lorsque le code de hachage de deux éléments est le même. .

efficace Java, 2e édition discute de cette règle (et des conséquences de la casser de la casser) dans Item 9: Toujours remplacer HashCode lorsque vous remplacez Equals .


1 commentaires

Merci beaucoup de gars, qui était vraiment utile, j'ai trouvé la réponse avant de répondre (je ne savais pas comment annuler la question), mais ce que vous avez écrit est ce que j'ai fait et cela a résolu mon problème;).



7
votes

Le hashset dépend du crockode de chaque objet. Avant que la méthode Equals est appelée, la méthode de code HASHCODE sera appelée. Si les critères sont égaux, le hashset le juge digne d'évaluer la méthode des égaux.

Implémentez une méthode de code HASHCODE telle que si A.Equals (B) == True, A.HashCode () == B.HashCode ()

Et cela devrait commencer à fonctionner comme vous l'attendez.


0 commentaires

0
votes

Comme la plupart des commentaires ont été ... il suffit de remplacer la méthode HashCode (exemple ci-dessous) et vous devriez être bon. XXX


2 commentaires

Que gagnez-vous en multipliant par 31?


ce fil aidera Stackoverflow.com/questions/299304/...