2010-06-02 5 views
8

Tôi đã có một lớp, "Accumulator", thực hiện phương thức compareTo Comparable, và tôi đang cố gắng đưa các đối tượng này vào một HashSet.Java HashSet cho phép thực hiện hai lần; vấn đề với so sánh?

Khi tôi thêm() vào HashSet, tôi không thấy bất kỳ hoạt động nào trong phương thức compareTo của mình trong trình gỡ lỗi, bất kể tôi đặt điểm ngắt của mình ở đâu. Ngoài ra, khi tôi hoàn thành với add() s, tôi thấy một số bản sao trong Set.

Tôi đang làm gì ở đây; tại sao nó không so sánh, và do đó, cho phép các dupes?

Cảm ơn,
IVR Avenger

Trả lời

15

Tôi đang làm gì ở đây?

HashSet được dựa trên hashCode(), không phải trên compareTo(). Bạn có thể gây nhầm lẫn với TreeSet. Trong cả hai trường hợp, hãy đảm bảo thực hiện equals() theo cách phù hợp với phương pháp khác.

10

Bạn cần phải thực hiện một cách chính xác hashCode()equals().

Bạn phải ghi đè hashCode và trả lại một số dựa trên các giá trị trong lớp của bạn sao cho bất kỳ hai đối tượng bằng nhau nào có cùng mã băm.

+0

mà không bằng nó sẽ hoàn toàn không hợp lệ. – Justin

1

HashSet sử dụng hashCode và bằng. TreeSet sử dụng giao diện Comparable. Lưu ý: nếu bạn quyết định ghi đè mã băm hoặc bằng, bạn nên luôn ghi đè mã khác.

+1

Bạn chỉ cần ghi đè hashCode nếu bằng được ghi đè (định nghĩa là bình đẳng đã thay đổi). Cách khác xung quanh không nhất thiết phải đúng. Hoàn toàn hợp pháp khi thay đổi hashCode để trả về 1 và để lại bằng một mình. –

2

Khi hàm hashCode trả về các giá trị khác nhau cho 2 đối tượng, khi đó giá trị bằng không được sử dụng. Btw, compareTo không có gì để làm với các bộ sưu tập băm :) nhưng bộ sưu tập được sắp xếp

2

đối tượng của bạn là Comparable, và có lẽ bạn đã thực hiện equals() quá, nhưng HashSets thỏa thuận với băm đối tượng, và tỷ lệ cược là bạn đã không được thực hiện hashCode() (hoặc thực hiện lại hashCode() không trả lại băm tương tự cho hai đối tượng là (a.equals(b) == true).

4

HashSet sử dụng các phương pháp hashCode()equals() để ngăn chặn bản sao từ được bổ sung. Đầu tiên, nó được mã băm của đối tượng bạn muốn Sau đó, nó tìm thấy thùng tương ứng cho t mã băm mũ và lặp qua từng đối tượng trong nhóm đó, sử dụng phương thức equals() để xem có bất kỳ đối tượng giống hệt nào đã tồn tại trong tập hợp hay không.

Trình gỡ lỗi của bạn không vi phạm trên compareTo() vì nó không bao giờ được sử dụng với HashSet!

Các quy tắc là:

  1. Nếu hai vật đều bình đẳng, sau đó mã băm của họ phải được bình đẳng.

  2. Nhưng nếu mã băm hai đối tượng đều bình đẳng, sau đó điều này không có nghĩa là các đối tượng đều bình đẳng!Nó có thể là rằng hai đối tượng chỉ xảy ra để có cùng một băm.

1

Khi bao giờ bạn tạo một đối tượng của lớp Accumulator phải mất không gian mới trong JVM và trả độc đáo hashCode mỗi khi bạn thêm một đối tượng trong HashSet. Nó không phụ thuộc vào giá trị của đối tượng vì bạn không ghi đè phương thức hashCode() do đó nó sẽ gọi phương thức đối tượng hashCode() sẽ trả về hashCode duy nhất với mọi đối tượng được tạo trong chương trình của bạn.

Giải pháp:

Override hashCode()equals() phương pháp và áp dụng logic của bạn phụ thuộc vào tính chất của lớp học của bạn. Hãy chắc chắn để đọc bằng và hợp đồng hashcode

http://www.ibm.com/developerworks/java/library/j-jtp05273/index.html

+0

liên kết được cung cấp là rất hữu ích và cho những người bininer thích tôi nó rất hữu ích. –

2

Một điều mà người dân có xu hướng bỏ qua đó dẫn đến một sai lầm rất lớn. Trong khi xác định phương thức equals luôn lấy tham số là lớp đối tượng và sau đó chuyển đối tượng đến lớp mong muốn của bạn. Đối với ví dụ

public bolean equals(Object aSong){ 
    if(!(aSoneg instanceof Song)){ 
     return false; 
    } 
    Song s=(Song) aSong; 
    return getTitle().equals(s.getTitle()); 
    } 

Nếu u vượt qua viết Sông aSong thay vì Object aSong bằng phương pháp của bạn sẽ không bao giờ được gọi.

Hy vọng điều này sẽ giúp