Question

Je ne peux pas sembler obtenir une instance HashSet pour fonctionner comme prévu. Le code j'est la suivante:

import testing.Subclass;
import java.util.HashSet;

public class tester {
  public static void main(String[] args) throws Exception {
    HashSet<Subclass> set = new HashSet<Subclass>();
    set.add(new Subclass("007812"));
    set.add(new Subclass("007813"));
    System.out.println("Set size " + set.size());
    set.add(new Subclass("007812"));
    System.out.println("Set size " + set.size());

    for(Subclass sub : set) {
      System.out.println(" sub acctNbr " + sub.getAcctNbr());
    }
  }
}

général

public class Subclass implements Comparable<Subclass> {

  public Subclass(String acctNbr) {
    this.acctNbr = acctNbr;
  }
  private String acctNbr;
  public String getAcctNbr() {
    return this.acctNbr;
  }
  public int compareTo(Subclass other) {
    return this.getAcctNbr().compareTo(other.getAcctNbr());
  }

  public boolean equals(Subclass other) {
    if(other.getAcctNbr().equals(this.getAcctNbr()))
      return true;
    else
      return false;
  }
  public int hashCode() {
    return acctNbr.hashCode();
  }
}

sorties de code

sross@sross-workstation:~/Documents$ javac testing/Subclass.java
sross@sross-workstation:~/Documents$ javac tester.java
sross@sross-workstation:~/Documents$ java tester
Set size 2
Set size 3
 sub acctNbr 007812
 sub acctNbr 007812
 sub acctNbr 007813
sross@sross-workstation:~/Documents$
Était-ce utile?

La solution

Vous devez passer outre equals(Object). Au lieu de faire cela, vous avez mis en place une méthode equals avec equals(Subclass) signature. Par conséquent, votre HashSet utilise la méthode equals(Object) par défaut défini sur Object pour les tests d'égalité.

La mise en œuvre par défaut equals(Object) est basée sur l'identité de l'objet, et par conséquent l'ensemble « permet » vous d'ajouter deux Strings qui, tout en sémantiquement égales, ne sont pas le même objet.

Autres conseils

Vous ne l'avez pas correctement substituez Object.equals().

@Override
public boolean equals(Object other) {
    if ((other == null) || !(other instanceof Subclass)) {
        return false;
    }
    return ((Sublcass) other).getAcctNbr().equals(this.getAcctNbr());
}

La boolean equals(Subclass other) méthode crée une seconde méthode qui est pas ce que vous aviez l'intention de le faire.

Deux méta-points:

Tout d'abord, prenez l'habitude d'utiliser @Override chaque fois que vous pensez que vous surchargez une méthode. Cela aurait causé votre code d'exemple à l'échec de la compilation, qui vous conduira à découvrir le problème.

En second lieu, si vous utilisez un IDE, et il n'a pas mis en évidence un bel avertissement gras pour vous, il est mal configuré! Vous devez réparer!

Et si vous ne l'utilisez un IDE - vous vraiment, si vraiment. Dès que vous avez saisi public boolean equals(Subclass other), le texte change de couleur et un avertissement sera affiché vous dire ce que votre problème est probablement.

Par ailleurs, l'idiome standard pour equals() que j'ai convergé sur est la suivante:

@Override public boolean equals(Object object) {
  if (object instanceof Subclass) {
    Subclass that = (Subclass) object;
    return this.anInt == that.anInt
        && this.aString.equals(that.aString); // for example
  }
  return false;
}

certains cas, il vaut la peine préfixer un if (object == this) { return true; } mais il est vraiment pas la peine de faire une habitude régulière de celui-ci.

J'ai eu presque le même problème, comme tout le monde dit que vous devez remplacer la bonne méthode de public boolean equals(Object o). Mais cela ne suffit pas!

Il est également nécessaire de passer outre public int hashCode() (comme vous l'avez fait), sinon, java ne serait pas appeler la méthode equals du tout.

Première supposition, il semble que votre equals(Subclass other) doit être equals(Object other) afin de passer outre la méthode java.lang.Object.equals(), comme vous voulez. Probablement l'ensemble appelle la mise en œuvre de equals() sous-jacente.

Votre méthode equals est jamais appelé. La signature de equals exige de prendre un Object, pas une autre classe (y compris ce que la classe arrive à mettre en œuvre equals).

public boolean equals(Object other) {
    ...
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top