Java Hashset.contient du (des) produit mystérieux résultat
Je n'ai pas l'habitude de code en Java, mais récemment, j'ai commencé à ne plus avoir le choix. Je pourrais avoir quelques malentendu majeur de comment utiliser correctement HashSet. Il pourrait donc être possible quelque chose que je fait est tout simplement faux. Cependant, je suis reconnaissant pour toute aide, vous pourriez offrir. Donc, le problème réel:
Dans un petit programme que j'écrivais, j'étais la génération très semblables objets, qui, lors de sa création, aurait très spécifiques id (un string
ou dans ma dernière itération d'une long
). Parce que chaque objet donnerait naissance à de nouveaux objets, je voulais filtrer tous ceux que j'ai déjà créé. J'ai donc commencé à jeter l'id de chaque nouvel objet dans mon Hash(Set) et d'essais avec HashSet.contains()
, si un objet a été créé avant. Voici le code complet:
//hashtest.java
import java.util.HashSet;
class L {
public long l;
public L(long l) {
this.l = l;
}
public int hashCode() {
return (int)this.l;
}
public boolean equals(L other) {
return (int)this.l == (int)other.l;
}
}
class hashtest {
public static void main(String args[]) {
HashSet<L> hash = new HashSet<L>();
L a = new L(2);
L b = new L(2);
hash.add(a);
System.out.println(hash.contains(a));
System.out.println(hash.contains(b));
System.out.println(a.equals(b));
System.out.println(a.hashCode() == b.hashCode());
}
}
produit la sortie suivante:
true
false
true
true
donc, apparemment, contains
ne pas utiliser le equals
fonction fournie par L
, ou je présente une certaine incompréhension de la notion ...
Je l'ai testé avec openjdk (version actuelle inclus dans ubuntu) et la vigueur officielle de java d'Oracle sur Win7
pour l'exhaustivité officiel de java-documentation de l'api pour HashSet.contains()
:
public boolean contains(Object o)
Retourne
true
si cet ensemble contient les
l'élément spécifié. Plus formellement,
retournetrue
si et seulement si cet ensemble
contient un élémente
tels que
(o==null ? e==null : o.equals(e))
.
http://download.oracle.com/javase/6/docs/api/java/util/HashSet.html#contains(java.lang.Objet)
Des idées ou des suggestions?
OriginalL'auteur Jochen | 2010-11-07
Vous devez vous connecter pour publier un commentaire.
Votre
equals
méthode doit prendre uneObject
.Parce que vous avez déclaré que la prise d'un
L
, il devient une surcharge supplémentaire au lieu de la substitution de la méthode.Par conséquent, lorsque le
hashSet
appels de classeequals
, il se résout à la baseObject.equals
méthode. Lorsque vous appelezequals
, vous appelez votre surcharge parce quea
etb
sont à la fois déclaré commeL
au lieu deObject
.Pour éviter ce problème à l'avenir, vous devez ajouter
@Override
chaque fois que vous remplacez une méthode.De cette façon, le compilateur vous avertira si ce n'est pas vraiment un remplacement.
OriginalL'auteur SLaks
Vous n'êtes pas vraiment primordial
Object.equals
; au lieu de cela, vous êtes à la définition d'une nouvelle méthode avec le même nom mais avec des paramètres différents. Notez queObject.equals
prend unObject
argument, alors que votre méthode equals prend unL
argument. Si vous réécrivez votre méthode equals pour prendre unObject
et réaliser la nécessaire vérification de type/moulage àL
au moment de l'exécution, puis votre code est qu'il fonctionne comme prévu.Aussi, c'est pourquoi vous devriez vraiment utiliser
@Override
annotations à chaque fois que votre JRE les prend en charge. De cette façon, le compilateur va se plaindre si vous avez accidentellement mettre en œuvre une nouvelle méthode lorsque vous avez l'intention de remplacer un existant.Par exemple, cette méthode equals devrait fonctionner correctement. (Et, sur une autre note, il ne sera pas échouer si l'objet de la comparaison est nulle.)
OriginalL'auteur bcat
Lors de l'ajout d'objets à un téléviseur, il appelle en interne
equals
ethashCode
méthodes. Vous devez remplacer ces deux méthodes. Par exemple, j'ai pris une classe d'haricot avecname
,id
,designation
, puis créé et ajouté unemployee
objet.set.add()
les appels à l'intérieur de l'equals
ethashCode
méthodes. Donc, vous avez à remplacer ces deux méthodes dans votre classe d'haricot.Nous sommes ici primordial
equals()
ethashCode()
. Lorsque vous ajoutez un objet à laHashSet
méthode en interne parcourt tous les objets et les appels de laequals
méthode. Par conséquent, nous overridhashCode
, il compare tous les objetshashCode
avec son actuelhashCode
et renvoie true si les deux sont égaux, sinon elle retourne false.OriginalL'auteur Jagadeesh