2010-12-14 33 views
7

Đối với một lớp học mà lĩnh vực hoàn toàn chịu nguyên thủy, ex .:Ghi đè hashCode() - điều này có đủ tốt không?

class Foo 
{ 
    int a; 
    String b; 
    boolean c; 
    long d; 

    boolean equals(Object o) 
    { 
     if (this == o) return true; 
     if (!(o instanceof Foo)) return false; 
     Foo other = (Foo) o; 
     return a == other.a && b.equals(other.b) && c == other.c && d = other.d; 
    } 
} 

Đây có phải là một cách hợp lý "đủ tốt" để viết hashCode()?

boolean hashCode() 
{ 
    return (b + a + c + d).hashCode(); 
} 

Đó là, tôi xây dựng một String ra khỏi các lĩnh vực tương tự mà equals() sử dụng, và sau đó chỉ cần sử dụng String#hashCode().

Chỉnh sửa: Tôi đã cập nhật câu hỏi của mình để bao gồm trường long. Làm thế nào nên một long được xử lý trong hashCode()? Chỉ cần để nó tràn int?

+0

Trong khi không hiệu quả khủng khiếp, nó sẽ hoạt động tốt vì bất kỳ hai trường hợp nào có cùng giá trị nội bộ sẽ có cùng mã băm. – Gabe

+0

Nó sẽ làm việc một cách chính xác tôi không biết về vấn đề hiệu suất về nó, nhưng nó chắc chắn sẽ làm việc. Nếu bạn muốn đi xa hơn thì hãy đọc: http://www.ibm.com/developerworks/java/library/j-jtp05273.html – Necronet

+0

Chỉ cần sử dụng [hashonsode] của [commons-lang] (http://commons.apache.org/ lang/api-2.5/org/apache/commons/lang/builder/HashCodeBuilder.html) và không bao giờ phải lo lắng loại điều này –

Trả lời

7

Mã băm của bạn không thỏa mãn thuộc tính nếu hai đối tượng bằng nhau, thì mã băm của chúng cần phải bằng nhau. Vì vậy, theo cách đó nó là 'đủ tốt'. Tuy nhiên, nó khá đơn giản để tạo ra xung đột trong các mã băm làm suy giảm hiệu suất của các cấu trúc dữ liệu dựa trên băm.

tôi sẽ thực hiện nó hơi khác nhau mặc dù:

public int hashCode() { 
    return a * 13 + b.hashCode() * 23 + (c? 31: 7); 
} 

Bạn nên kiểm tra documentation for the hashCode() method của Object. Nó đưa ra những điều mà mã băm phải thỏa mãn.

+0

Tôi hiểu hợp đồng cho 'equals()' và 'hashCode()'. Những gì tôi đang tìm kiếm là một nỗ lực tối thiểu, chống bạo lực, không có cách bất ngờ để hoàn thành hợp đồng. Mã của bạn có vẻ đủ hợp lý. Bạn có thể giải thích lý do nhân với số nguyên tố? Ngoài ra, tôi đã cập nhật câu hỏi của mình: làm cách nào để xử lý các trường 'long'? –

+3

@Matt - Đường dẫn "nỗ lực tối thiểu", chống bạo động "đang sử dụng IDE của bạn để tạo phương pháp. Ví dụ: Netbeans tạo cho một trong các lớp của tôi:' int hash = 5; hash = 37 * hash + (int) (this. id^(this.id >>> 32)); băm trả về; ' –

+1

@Coronatus: hmm, điểm tốt. Tôi quên mất' Alt + Shift + S' (Eclipse) –

0

Nó hoàn toàn phụ thuộc vào dữ liệu của bạn sẽ trông như thế nào. Trong hầu hết các trường hợp, đây sẽ là một cách tiếp cận tốt. Nếu bạn thường có kết thúc b với một số, thì bạn sẽ nhận được một số mã trùng lặp cho các đối tượng không bằng nhau, như câu trả lời của JacobM hiển thị. Nếu bạn biết trước rằng b sẽ không bao giờ có giá trị số ở cuối, thì đây là một thuật toán băm hợp lý.

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