12 Stimmen

hashCode()-Methode, wenn equals() auf mehreren unabhängigen Feldern basiert

Ich habe eine Klasse, deren Gleichheit auf 2 Felder basiert, so dass, wenn entweder eine gleich ist, dann die Objekte dieses Typs als gleich betrachtet werden. wie kann ich eine HashCode()-Funktion für eine solche equals() schreiben, so dass der allgemeine Vertrag der HashCode gleich ist, wenn equals wahr zurückgibt, erhalten bleibt?

public class MyClass {
  int id;
  String name;

  public boolean equals(Object o) {
    if (!(o instanceof MyClass))
      return false;
    MyClass other = (MyClass) o;
    if (other.id == this.id || other.name == this.name)
      return true;
    return false;
  }
}

wie schreibe ich eine HashCode()-Funktion für diese Klasse? und ich möchte den trivialen Fall hier der Rückkehr eine Konstante wie so zu vermeiden:

public int hashCode() {
  return 1;
}

0voto

Dennis C Punkte 23918

EDIT: Ich habe die Frage nicht sorgfältig gelesen.

--

Ich werde commons-lang jar verwenden.

XOR der Mitglieder hashCode sollte funktionieren. Da sie hashCode() und equals() korrekt implementieren sollten.

Ihr Code kann jedoch falsch sein, wenn Sie Ihren hashCode nicht schützen. Sobald er gehasht wurde, sollte er nicht mehr geändert werden. Es sollte verhindert werden, dass er passiert.

public hashCode(){
   return new AssertionError();
}

ou

 public class MyClass {
   final int id;
   final String name;
   // constructor
 }

ou

public class MyClass {
   private int id;
   private String name;
   boolean hashed=false;
   public void setId(int value){
     if(hashed)throw new IllegalStateException();
     this.id=value;
   }
   public void setName(String value){
     if(hashed)throw new IllegalStateException();
     this.name=value;
   }
   // your equals() here
   public hashCode(){
     hashed=true;
     return new HashCodeBuilder().append(id).append(name).toHashCode();
   }
}

0voto

Dennis C Punkte 23918

Nachdem ich die Frage erneut gelesen habe.

Sie können das andere Feld automatisch ausfüllen, wenn eines der Felder aktualisiert wird.

--

EDIT: Mein Code ist vielleicht besser als mein Englisch.

void setName(String value){
  this.id=Lookup.IDbyName(value);
}
void setID(String value){
  this.name=Lookup.NamebyId(value);
}

EDIT 2 :

Der Code in der Frage kann falsch sein, da er immer true zurückgibt, es sei denn, Sie haben sowohl die id als auch den Namen festgelegt.

Wenn Sie wirklich eine Methode, die teilweise gleich tun wollen, erstellen Sie Ihre eigene API, die "partialEquals()" genannt.

-1voto

Brian Punkte 24901

Der einfachste Weg ist das XOR der Hashcodes jedes einzelnen Feldes. Dies ist in einigen Situationen etwas hässlich (z.B. bei X,Y-Koordinaten führt es zu der potenziell schlechten Situation, dass man gleiche Hashes hat, wenn man X und Y umdreht), ist aber insgesamt recht effektiv. Tweak als erforderlich, um Kollisionen zu reduzieren, wenn für die Effizienz erforderlich.

-1voto

Peter Punkte 34999

Wie wäre es damit

public override int GetHashCode()
{
    return (id.ToString() + name.ToString()).GetHashCode();
}

Die Funktion sollte immer einen "gültigen" Hash zurückgeben...

Edit: Ich habe gerade bemerkt, dass du "oder" und nicht "und" benutzt :P Nun, ich bezweifle, dass es eine gute Lösung für dieses Problem gibt...

-2voto

Ed S. Punkte 118985

Wie wäre es mit

public override int GetHashCode()
{
    return id.GetHashCode() ^ name.GetHashCode();
}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X