Bộ băm hoạt động với "nhóm". Nó lưu trữ các giá trị trong các "nhóm" đó theo mã băm của chúng. Một "xô" có thể có một số thành viên trong đó, tùy thuộc vào việc các thành viên đó có bình đẳng hay không, bằng cách sử dụng phương thức equals(Object)
.
Vì vậy, giả sử chúng ta xây dựng một bộ băm với 10 nhóm, vì mục đích của đối số và thêm các số nguyên 1, 2, 3, 5, 7, 11 và 13 vào nó. Mã băm cho một int chỉ là int. Chúng tôi kết thúc với một cái gì đó như thế này:
- (trống)
- 1, 11
- 3, 13
- (trống)
- (trống)
- (trống)
- (trống)
Cách truyền thống để sử dụng bộ là xem và xem một thành viên có trong bộ đó không. Vì vậy, khi chúng ta nói, "Có 11 trong bộ này?" bộ băm sẽ modulo 11 lên 10, lấy 1 và tìm trong nhóm thứ hai (chúng tôi đang bắt đầu nhóm của chúng tôi với 0 tất nhiên).
Điều này làm cho nó thực sự, thực sự nhanh chóng để xem các thành viên thuộc về một tập hợp hay không. Nếu chúng tôi thêm một 11 khác, bộ băm sẽ xem liệu nó đã có ở đó chưa. Nó sẽ không thêm nó một lần nữa nếu nó được. Nó sử dụng phương pháp equals(Object)
để xác định điều đó và tất nhiên, 11 bằng 11.
Mã băm cho chuỗi như "abc" phụ thuộc vào các ký tự trong chuỗi đó. Khi bạn thêm một chuỗi trùng lặp, "abc", bộ băm sẽ tìm trong nhóm bên phải và sau đó sử dụng phương thức equals(Object)
để xem liệu thành viên đã có ở đó chưa. Phương thức equals(Object)
cho chuỗi cũng phụ thuộc vào các ký tự, vì vậy "abc" bằng "abc".
Khi bạn sử dụng một StringBuffer, mặc dù, mỗi StringBuffer có một mã băm, và bình đẳng, dựa trên ID đối tượng của nó. Nó không ghi đè các phương thức cơ bản equals(Object)
và hashCode()
, vì vậy mọi StringBuffer đều nhìn vào bộ băm giống như một đối tượng khác. Chúng không thực sự trùng lặp.
Khi bạn in StringBuffers vào đầu ra, bạn đang gọi phương thức toString() trên StringBuffers. Điều đó làm cho chúng trông giống như chuỗi trùng lặp, đó là lý do tại sao bạn nhìn thấy đầu ra đó.
Đây cũng là lý do rất quan trọng để ghi đè hashCode()
nếu bạn ghi đè equals(Object)
, nếu không, Bộ sẽ nhìn vào nhóm không đúng và bạn nhận được hành vi rất kỳ lạ và không thể đoán trước!
StringBuffer không ghi đè bằng()/hashCode(), do đó, mỗi thể hiện StringBuffer sẽ được thêm vào Set, bất kể nội dung của StringBuffer. – proko
@proko Hàm hashCode() chỉ đảm bảo rằng nó trông trong nhóm thích hợp cho mục đó. Nó thực sự là phương thức equals() gây ra các bản sao. Nó sẽ là có thể (mặc dù không phải là rất performant) để tạo ra một lớp StringBuffer đã có chính xác cùng một hashCode, nhưng bình đẳng khác nhau, và họ sẽ được công nhận là cá nhân quá. – Lunivore
@Lunivore: vâng tôi biết điều đó. Nhưng nhìn vào câu trả lời khác ở đây, có vẻ như quen thuộc để đề cập đến cả hai phương pháp cho bối cảnh này. – proko