2013-05-04 13 views
15

Ich versuche, eine HashCode() -Methode für meine einfache Klasse zu generieren, aber ich komme nicht damit. Ich würde jede Hilfe schätzen. Ich habe die equals() -Methode implementiert, die wie folgt aussieht, und möchte auch wissen, ob ich die compareTo() -Methode implementieren muss. Ich habe java.lang.Character importiert, um character.hashCode() zu verwenden, aber es scheint nicht zu funktionieren.Wie schreibe ich HashCode-Methode für eine bestimmte Klasse?

private class Coord{ 
    private char row; 
    private char col; 
    public Coord(char x, char y){ 
     row = x; 
     col = y; 
    } 
    public Coord(){}; 

    public char getX(){ 
     return row; 
    } 

    public char getY(){ 
     return col; 
    } 

    public boolean equals(Object copy){ 
     if(copy == null){ 
      throw new NullPointerException("Object entered is empty"); 
     } 
     else if(copy.getClass()!=this.getClass()){ 
      throw new IllegalArgumentException("Object entered is not Coord"); 
     } 
     else{ 
      Coord copy2 = (Coord)copy; 
      if(copy2.row==this.row && copy2.col==this.col) 
       return true; 
      else 
       return false; 
     } 
    } 

} 

Vielen Dank im Voraus ...

Die comparto() -Methode, die mir java.lang.Comparable Gussfehler ..

public int compareTo(Object copy){ 
     if(copy==null){ 
      throw new NullPointerException("Object entered is empty"); 
     } 
     else if(copy.getClass()!=this.getClass()){ 
      throw new IllegalArgumentException("Object entered is not Coord"); 
     } 
     else{ 
      Coord copy2 = (Coord)copy; 
      if(copy2.row==this.row && copy2.col==this.col){ 
       return 0; 
      } 
      else if(copy2.col < this.col){ 
       return -1; 
      } 
      else{ 
       return 1; 
      } 
     } 
    } 

Dank schenkt ...

+0

Ich denke, [Zwingende gleich und hashCode in Java] (http://stackoverflow.com/questions/27581/overriding-equals-and-hashcode-in-java?rq=1) wird Ihnen helfen. –

Antwort

16

Um hashCode zu implementieren, überschreiben Sie die Standardimplementierung von Objekt:

@Override 
public int hashCode() 
{ 
    return row^col; 
} 

Dies ist nicht wirklich ein idealer Hash, da seine Ergebnisse sehr vorhersehbar sind und es für zwei verschiedene Coord Objekte leicht ist, den gleichen Wert zurückzugeben. Eine bessere Hash würde die Verwendung der eingebauten in Arrays Klasse von java.util (http://docs.oracle.com/javase/7/docs/api/java/util/Arrays.html) machen:

@Override 
public int hashCode() 
{ 
    return Arrays.hashCode(new Object[]{new Character(row), new Character(col)}); 
} 

Mit dieser Methode kann eine ziemlich gute Hash mit einem beliebigen Anzahl von Feldern zu erzeugen.

Zur Umsetzung compareTo, werden Sie Ihre Klasse wollen Comparable implementieren:

public class Coord implements Comparable<Coord> 

Sobald Sie dies getan haben, können Sie Coord eher ein Argument vom Typ compareTo nehmen machen als Typ Object, die sparen Sie haben die Mühe, seinen Typ zu überprüfen.

+0

Sie brauchen Java 7 nicht, wenn Sie 'Arrays.hashCode (Object [] args)' verwenden, das seit 1.5 in Java ist. – durron597

+0

@ durron597 Guter Punkt, ich werde es aktualisieren – nullptr

+0

@ durron597 Ich habe auch einen Vergleich geschrieben() -Methode thatlooks wie 'public int compareTo (Object copy) { \t \t \t if (Kopie == null) { \t \t \t \t Wurf neue Nullpointer ("Objekt eingetragen ist leer"); \t \t \t} \t \t \t else if (copy.getClass() = this.getClass()!) { \t \t \t \t throw new Illegal ("Objekt eingetragen ist nicht Coord"); \t \t \t} \t \t \t else { \t \t \t \t Coord copy2 = (Coord) copy; \t \t \t \t if (copy2.row == this.row && copy2.col == this.col) { \t \t \t \t \t return 0; \t \t \t \t} \t \t \t \t else if (copy2.col

13

Hashcode ist ein int (32 Bit), ist Ihre Daten char (16 Bit), so würde ich wahrscheinlich nur tun:

@Override 
public int hashCode() { 
    return (row << 16) + col; 
} 

Dies stellt den Bits von row in den ersten 16 Bits und die Bits von col in den letzten 16 Bits, so ist dies ein perfect hash function für diese Klasse.

Wenn Sie Ihre Klasse komplizierter gestalten, empfehle ich die Antwort von nullptr.


Comparable zu verwenden, machen:

public class Coord implements Comparable<Coord> 
+5

Verzeihen Sie, wenn ich falsch liege, aber Sie werden nie Zusammenstöße haben; Die möglichen Objekte scheinen 1: 1 mit den möglichen HashCodes abzubilden. Und das sollte wirklich schnell sein, also ist dies eine großartige Antwort. –

+0

Ja. "Ziemlich unwahrscheinlich" unterschätzt es. Dies ist tatsächlich eine perfekte Hash-Funktion für ein Paar Zeichen; Zwei Objekte haben denselben Hash-Code, wenn und nur wenn sie gleiche Werte darstellen. – cHao

+0

@CoryKendall Nun, erinnern Sie sich, eine 'HashMap' verwendet Modulo auf dem' hashCode() 'Wert, es enthält nicht 2^32 mögliche Zellen. Für bestimmte Charaktere und Modulus- und HashMap-Größen wird es immer noch Kollisionen geben. Allerdings stimme ich zu Ich hätte es besser formulieren können :) – durron597

5

ich sehr wertvolle Informationen zu diesem Thema und viele anderen Themen in den Effective Java book, written by Joshua Bloch gefunden. Auf Seite 45 finden Sie weitere Informationen zu hashCode() und equals(). Wenn Sie eine IDE wie Eclipse verwenden, können Sie die Methoden hashCode() und equals() generieren lassen.Für Ihre Klasse wäre das Ergebnis:

class Coord implements Comparable<Coord> { 

    private char row; 
    private char col; 

    public Coord(char x, char y) { 
     row = x; 
     col = y; 
    } 

    public Coord() { 
    }; 

    public char getX() { 
     return row; 
    } 

    public char getY() { 
     return col; 
    } 

    @Override 
    public int hashCode() { 
     final int prime = 31; 
     int result = 1; 
     result = prime * result + col; 
     result = prime * result + row; 
     return result; 
    } 

    @Override 
    public boolean equals(Object obj) { 
     if (this == obj) 
      return true; 
     if (obj == null) 
      return false; 
     if (getClass() != obj.getClass()) 
      return false; 
     Coord other = (Coord) obj; 
     if (col != other.col) 
      return false; 
     if (row != other.row) 
      return false; 
     return true; 
    } 

    public int compareTo(Coord param) { 
     // Implementation according to http://docs.oracle.com/javase/7/docs/api/java/lang/Comparable.html 
     return 0; 
    } 

} 
+0

Ich weiß, das ist eine ziemlich typische Implementierung, aber es hat einige knifflige numerische Nachteile. Wenn Sie nur zwei Komponenten haben - wie hier -, die beide den gleichen Wert haben (kein ungewöhnliches Vorkommen), entspricht dies 32 'Hash + Offset', das 5 weniger Entropie als Ihre Quelle hat Hash. Nicht ideal. –

-1

ähnlich wie durron597 Antwort, können Sie versuchen, diese Option, wenn Sie die Eingabe mit char begrenzt ist (zwischen 0 und 65535)

public int hashCode(){ 
    return row * 100000 + col; 
} 
+0

Diese Antwort ist überflüssig, und obwohl sie korrekt ist, ist sie schwierig, weil sie eine nicht-offensichtliche magische Zahl enthält, die nur funktioniert, weil sie größer oder gleich 65536 ist –