2013-05-04 18 views
15

Próbuję wygenerować metodę hashCode() dla mojej prostej klasy, ale nie dostaję się z tym. Byłbym wdzięczny za każdą pomoc. Zaimplementowałem metodę equals(), która wygląda następująco, i chciałbym również wiedzieć, czy muszę zaimplementować metodę compareTo(). Zaimportowałem plik java.lang.Character, aby użyć znaku character.hashCode(), ale wydaje się, że nie działa.Jak napisać metodę hashCode dla konkretnej klasy?

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; 
     } 
    } 

} 

góry dzięki ...

Sposób comparTo(), która daje mi java.lang.Comparable błąd rozstrzygający ..

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; 
      } 
     } 
    } 

Dzięki ...

+0

myślę [Zastępowanie równa i hashcode w Javie] (http://stackoverflow.com/questions/27581/overriding-equals-and-hashcode-in-java?rq=1) pomoże. –

Odpowiedz

16

Aby zaimplementować kod haszowania, zastępujesz domyślną implementację z obiektu:

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

To nie jest idealna hasza, ponieważ jej wyniki są bardzo przewidywalne i łatwo dwa różne obiekty o wartości Coord zwracają tę samą wartość. Lepszym hash będzie skorzystać z wbudowanego w Arrays klasy z java.util (http://docs.oracle.com/javase/7/docs/api/java/util/Arrays.html):

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

Można użyć tej metody, aby wygenerować dość dobry skrót z dowolnej liczby pól.

celu realizacji compareTo, będziemy chcieli klasa wdrożyć Comparable:

public class Coord implements Comparable<Coord> 

Gdy już to zrobisz, możesz zrobić compareTo przyjąć argumentu typu Coord zamiast typu Object, który pozwoli zaoszczędzić masz problem z sprawdzeniem jego typu.

+0

Nie potrzebujesz Java 7, jeśli używasz 'Arrays.hashCode (Object [] args)', który jest w Javie od 1.5 – durron597

+0

@ durron597 Dobra uwaga, zaktualizuję go – nullptr

+0

@ durron597 Napisałem również comparTo() metoda thatlooks jak 'public int compareTo (kopia Object) { \t \t \t if (kopia == null) { \t \t \t \t throw new NullPointerException ("Obiekt wpisany jest pusta"); \t \t \t} \t \t \t else if (copy.getClass() = this.getClass (!)) { \t \t \t \t rzut nowy IllegalArgumentException ("obiekt wprowadzony nie COORD"); \t \t \t} \t \t \t else { \t \t \t \t Coord Kopiuj2 = (Coord) kopii; \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

Kod źródłowy stanowi int (32 bitów), dane są char (16 bitów), więc pewnie po prostu zrobić:

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

Stawia to bity od row w pierwszych 16 bitów i bitów od col w ostatnich 16 bitach, więc jest to perfect hash function dla tej klasy.

Jeśli zmienisz klasę, aby była bardziej skomplikowana, polecam użycie odpowiedzi nullptr.


Aby korzystać Comparable, zrobić:

public class Coord implements Comparable<Coord> 
+5

Przebacz mi, jeśli się mylę, ale nigdy nie będziesz miał kolizji; możliwe obiekty wydają się mapować 1-do-1 z możliwymi hashCodes. A to powinno być naprawdę szybkie, więc jest to niesamowita odpowiedź. –

+0

Tak. "Dość mało prawdopodobne" to zaniża. Jest to właściwie doskonała funkcja hash dla pary znaków; dwa obiekty będą miały ten sam kod skrótu, jeśli i tylko jeśli będą reprezentować równe wartości. – cHao

+0

@CoryKendall Pamiętaj, że 'HashMap' używa modułu na wartości' hashCode() ', nie zawiera 2^32 możliwych komórek. Tak więc dla niektórych postaci i modułów oraz rozmiarów 'HashMap' nadal będą występowały kolizje. Zgadzam się jednak, że mogłem to sformułować lepiej :) – durron597

5

znalazłem bardzo cenne informacje dotyczące tego tematu i wiele innych tematów w Effective Java book, written by Joshua Bloch. Spójrz na stronę 45, aby uzyskać dalsze informacje na temat hashCode() i equals().

Jeśli używasz IDE takiego jak Eclipse, możesz pozwolić mu generować metody hashCode() i equals().Na swojej klasie wynik byłby:

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

Wiem, że jest to dość typowa implementacja, ale ma kilka trudnych liczbowych wad. Jeśli masz tylko dwa składniki, które mieszasz - takie jak tutaj - i oba mają tę samą wartość (nie jest to niezwykłe zdarzenie), jest to równoważne "32 * hash + offset", które ma 5 mniej bitów entropii niż twoje źródło haszysz. Nieidealny. –

-1

podobna do odpowiedzi durron597, można spróbować tego, czy wejście jest ograniczony przez char (między 0 a 65535)

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

Ta odpowiedź jest zbędna, a mimo że jest poprawna, jest trudna, ponieważ zawiera nieoczywistą liczbę magiczną, która działa tylko dlatego, że jest większa lub równa 65536 –

Powiązane problemy