2013-05-04 33 views
15

Tôi đang cố gắng để tạo ra một phương thức hashCode() cho lớp đơn giản của tôi nhưng tôi không nhận được bất cứ nơi nào với nó. Tôi sẽ đánh giá cao sự giúp đỡ nào. Tôi đã thực hiện phương thức equals(), trông giống như sau, và cũng muốn biết nếu tôi cần phải thực hiện phương thức compareTo(). Tôi đã nhập java.lang.Character để sử dụng character.hashCode() nhưng nó dường như không hoạt động.Làm thế nào để viết phương thức hashCode cho một lớp cụ thể?

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

} 

Cảm ơn trước ...

Các comparTo() phương pháp đó là đem lại cho tôi lỗi đúc java.lang.Comparable ..

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

nhờ ...

+0

Tôi nghĩ [Overriding equals và hashCode trong Java] (http://stackoverflow.com/questions/27581/overriding-equals-and-hashcode-in-java?rq=1) sẽ giúp bạn. –

Trả lời

16

Để triển khai hashCode, bạn ghi đè triển khai mặc định từ Object:

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

Đây không thực sự là một băm lý tưởng, vì kết quả của nó rất dễ dự đoán và dễ dàng cho hai đối tượng Coord khác nhau để trả về cùng một giá trị. Một băm tốt hơn sẽ tận dụng được xây dựng trong Arrays lớp từ 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)}); 
} 

Bạn có thể sử dụng phương pháp này để tạo một hash khá tốt với bất kỳ số lượng các lĩnh vực.

Thực hiện compareTo, bạn sẽ muốn lớp học của bạn để thực hiện Comparable:

public class Coord implements Comparable<Coord> 

Một khi bạn đã làm điều này, bạn có thể làm compareTo mất một đối số kiểu Coord chứ không phải là loại Object, mà sẽ tiết kiệm bạn gặp rắc rối khi kiểm tra loại của nó.

+0

Bạn không cần Java 7 nếu bạn sử dụng 'Arrays.hashCode (Object [] args)' đã có trong Java từ 1,5 – durron597

+0

@ durron597 Điểm tốt, tôi sẽ cập nhật nó – nullptr

+0

@ durron597 Tôi cũng đã viết một so sánh() phương pháp thatlooks như 'public int compareTo (bản sao Object) { \t \t \t if (bản sao == null) { \t \t \t \t ném NullPointerException mới ("Object vào là trống rỗng"); \t \t \t} \t \t \t else if (copy.getClass() = this.getClass()!) { \t \t \t \t ném IllegalArgumentException mới ("Object nhập vào không coord"); \t \t \t} \t \t \t else { \t \t \t \t Coord copy2 = (Coord) bản sao; \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

Mã lệnh bí mật là một int (32 bit), dữ liệu của bạn là char (16 bit), vì vậy tôi sẽ có lẽ chỉ làm:

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

Điều này đặt các bit từ row trong 16 bit đầu tiên và bit từ col trong 16 bit cuối cùng, vì vậy đây là số perfect hash function cho lớp này.

Nếu bạn cấu trúc lại lớp của mình phức tạp hơn, tôi khuyên bạn nên sử dụng câu trả lời của nullptr.


Để sử dụng Comparable, làm:

public class Coord implements Comparable<Coord> 
+5

Tha thứ cho tôi nếu tôi sai, nhưng bạn sẽ không bao giờ có va chạm; các đối tượng có thể dường như ánh xạ 1-to-1 với hashCodes có thể. Và điều này nên thực sự nhanh chóng, vì vậy đây là một câu trả lời tuyệt vời. –

+0

Đúng. "Khá chắc chắn" là understating nó. Đây thực sự là một hàm băm hoàn hảo cho một cặp ký tự; hai đối tượng sẽ có cùng mã băm nếu, và chỉ khi nào, chúng đại diện cho các giá trị bằng nhau. – cHao

+0

@CoryKendall Vâng, hãy nhớ rằng, một 'HashMap' sử dụng mô đun trên giá trị' hashCode() ', nó không chứa 2^32 ô có thể. Vì vậy, đối với một số ký tự và mô đun và kích thước 'HashMap' nhất định, nó sẽ vẫn có xung đột. Tuy nhiên, tôi đồng ý tôi có thể đã phrased nó tốt hơn :) – durron597

5

tôi thấy thông tin rất có giá trị liên quan đến chủ đề này và nhiều chủ đề khác trong Effective Java book, written by Joshua Bloch. Xem trang 45 để biết thêm thông tin về hashCode() và equals().

Nếu bạn sử dụng IDE như Eclipse, bạn có thể cho phép tạo phương thức hashCode()equals().Đối với lớp học của bạn kết quả sẽ là:

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

Tôi biết đây là một triển khai khá điển hình, nhưng nó có một số nhược điểm số khó. Nếu bạn chỉ có hai thành phần mà bạn đang băm - chẳng hạn như ở đây - và cả hai đều có cùng giá trị (không phải là một sự xuất hiện bất thường), điều này tương đương với '32 * hash + offset' có 5 bit entropy ít hơn nguồn của bạn băm. Không lý tưởng. –

-1

tương tự như câu trả lời durron597, bạn có thể thử này nếu đầu vào của bạn được bao bọc bởi char (giữa 0 và 65535)

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

Câu trả lời này là dư thừa, và trong khi nó là chính xác, nó phức tạp bởi vì nó bao gồm một số ma thuật không rõ ràng chỉ hoạt động bởi vì nó lớn hơn hoặc bằng 65536 –

Các vấn đề liên quan