2012-01-31 27 views
5

Hãy xem xét thêm một phương pháp bình đẳng để các lớp sau đây của điểm đơn giản:Làm thế nào để Viết một phương pháp bình đẳng trong Java

public class Point { 

    private final int x; 
    private final int y; 

    public Point(int x, int y) { 
     this.x = x; 
     this.y = y; 
    } 

    public int getX() { 
     return x; 
    } 

    public int getY() { 
     return y; 
    } 

    // ... 
} 

// định nghĩa của tôi về bình đẳng

public boolean equals(Point other) { 
    return (this.getX() == other.getX() && this.getY() == other.getY()); 
} 

Có gì sai với phương pháp này? Thoạt nhìn, có vẻ như để làm việc OK:

Point p1 = new Point(1, 2); 
Point p2 = new Point(1, 2); 

Point q = new Point(2, 3); 

System.out.println(p1.equals(p2)); // prints true 

System.out.println(p1.equals(q)); // prints false 

Tuy nhiên, rắc rối bắt đầu khi bạn bắt đầu đặt điểm vào một bộ sưu tập:

import java.util.HashSet; 

HashSet<Point> coll = new HashSet<Point>(); 
coll.add(p1); 

System.out.println(coll.contains(p2)); // prints false 

Làm thế nào nó có thể được rằng coll không chứa p2, mặc dù p1 được thêm vào nó, và p1 và p2 là các đối tượng bằng nhau?

+0

Giải thích tốt ở đây: http://bytes.com/topic/java/insights/723476-overriding-equals-hashcode-methods Nội dung hóa - đây là một trong những quy tắc cơ bản nhất trong Java và câu hỏi phỏng vấn thường xuyên. –

Trả lời

8

Mặc dù bạn thực hiện hashCode() khi bạn triển khai equals(), điều đó không gây ra sự cố của bạn.

Đó không phải là phương pháp equals() bạn đang tìm kiếm. Phương thức equals phải luôn có chữ ký sau: "boolean equals công cộng (Object object)". Đây là một số mã.

public boolean equals(Object object) 
{ 
    if (object == null) 
    { 
    return false; 
    } 

    if (this == object) 
    { 
    return true; 
    } 

    if (object instanceof Point) 
    { 
    Point point = (Point)object; 
    ... now do the comparison. 
    } 
    else 
    { 
    return false; 
    } 
} 

Apache EqualsBuilder class hữu ích cho việc triển khai thực hiện.Liên kết là phiên bản cũ hơn nhưng vẫn áp dụng được.

Nếu bạn thích Apache EqualsBuilder, có thể bạn cũng sẽ thích Apache HashCodeBuilder class.

Chỉnh sửa: đã cập nhật ví dụ phương thức bằng cho các phím tắt chuẩn.

+1

Được bình chọn cho bài đăng duy nhất để chỉ ra điều này. –

+0

@Louis: Hầu như chỉ một ... :-) – Dirk

+0

Vâng. Người duy nhất nhận xét của tôi mà tôi đã thấy. –

4

Bạn phải triển khai hashCode() bất cứ khi nào bạn ghi đè equals(). Hai người này làm việc cùng nhau, và họ phải đưa ra kết quả nhất quán mọi lúc. Không làm như vậy chỉ tạo ra hành vi sai lầm mà bạn quan sát được.

Điều này được giải thích chi tiết hơn, ví dụ: trong Effective Java 2nd Edition, Mục 9: Luôn ghi đè mã băm khi bạn ghi đè bằng.

0

Khi ghi đè equals, bạn cũng phải ghi đè hashCode (đặc biệt, nếu bạn định sử dụng HashSet hoặc HashMap ...). A (mặc dù không thông minh) thực hiện phù hợp sẽ là:

int hashCode() { 
    return x * 31 + y; 
} 

Một điểm (không có ý định chơi chữ): Bạn đang không thực sự trọng các equals(Object) phương pháp quy định tại lớp Object, nhưng thay vào đó là việc xác định một hình mới. Cách đúng sẽ là:

boolean equals(Object other) { 
    if (other == this) return true; 
    else if (!(other instanceof Point)) return false; 
    else { 
     Point p = (Point)other; 
     return x == p.getX() && y == p.getY(); 
    } 
} 

Lưu ý, rằng phương pháp equalspretty strong contract liên kết với nó, mà bạn đang thực hiện.

1

Theo hợp đồng trên equals(), bạn cũng cần triển khai hashCode().

Từ JavaDoc trên equals():

Lưu ý rằng nó nói chung là cần thiết để ghi đè lên phương thức hashCode bất cứ khi nào phương pháp này được ghi đè, để duy trì hợp đồng chung cho các phương thức hashCode, trong đó nêu rằng đối tượng bằng nhau phải có mã băm bằng nhau.

1

Bên cạnh những câu trả lời khác:

Nếu bạn đang sử dụng Eclipse như IDE, bạn chỉ có thể sử dụng "Source" -> "Generate hashCode() và equals() để có được một thực hiện cơ bản làm với. .! rằng những gì đã bao giờ bạn muốn

2

Hoạt động tốt bằng cách ghi đè hashcode

Luôn luôn nhớ:. ghi đè hashCode khi bạn ghi đè lên bằng

@Override public int hashCode() { 
     return (41 * (41 + getX()) + getY()); 
    } 

Đây là triển khai của tôi về hashCode.

+0

Điều này không tạo ra một hash duy nhất ... 2 ví dụ đơn giản 'x = 1',' y = 0', 'Hash = 1722' HOẶC' x = 0', 'y = 41',' Hash = 1722' – Basic

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