Boolean.hashCode ()


122

Các hashCode()phương pháp của lớp Boolean được thực hiện như thế này:

public int hashCode() {
    return value ? 1231 : 1237;
}

Tại sao nó sử dụng 1231 và 1237? Tại sao không phải cái gì khác?


1
Hai số này là số nguyên tố đủ lớn. Vui lòng đọc bài viết trên Bảng băm trên Wikipedia để biết thêm thông tin.
Boris Pavlović

Câu trả lời:


140

1231 và 1237 chỉ là hai số nguyên tố tùy ý (đủ lớn) . Bất kỳ hai số nguyên tố lớn nào khác đều tốt.

Tại sao lại là số nguyên tố?
Giả sử trong một giây mà chúng tôi chọn các số tổng hợp (không phải số nguyên tố), giả sử là 1000 và 2000. Khi chèn các boolean vào bảng băm, truefalse sẽ đi vào bucket 1000 % Nresp 2000 % N(ở đó Nlà số nhóm).

Bây giờ hãy để ý rằng

  • 1000 % 8 cùng một thùng như 2000 % 8
  • 1000 % 10 cùng một thùng như 2000 % 10
  • 1000 % 20 cùng một thùng như 2000 % 20
  • ....

nói cách khác, nó sẽ dẫn đến nhiều va chạm .

Điều này là do thừa số của 1000 (2 3 , 5 3 ) và thừa số của năm 2000 (2 4 , 5 3 ) có rất nhiều thừa số chung. Do đó, các số nguyên tố được chọn, vì chúng không có khả năng có bất kỳ thừa số chung nào với kích thước nhóm.

Tại sao số nguyên tố lớn . 2 và 3 sẽ không làm gì?
Khi tính toán mã băm cho các đối tượng hỗn hợp, thông thường sẽ thêm mã băm cho các thành phần. Nếu các giá trị quá nhỏ được sử dụng trong một tập hợp băm với số lượng lớn các nhóm thì có nguy cơ dẫn đến sự phân bố các đối tượng không đồng đều.

Va chạm có quan trọng không? Boolean chỉ có hai giá trị khác nhau?
Bản đồ có thể chứa boolean cùng với các đối tượng khác. Ngoài ra, như Drunix đã chỉ ra, một cách phổ biến để tạo các hàm băm của các đối tượng hỗn hợp là sử dụng lại các triển khai mã băm của các thành phần con, trong trường hợp đó, tốt hơn là trả về các số nguyên tố lớn.

Câu hỏi liên quan:


1
Tôi cho rằng chúng đủ lớn. Để có được gcd lớn hơn 1, bạn cần ít nhất 2*1231 = 2462nhóm. Có phải va chạm là một vấn đề trong tình huống như vậy?
aioobe

2
Tuy nhiên, điều thú vị là chúng không thực sự "khá lớn" khi xem xét những gì có thể phù hợp với một int. Tôi cho rằng chúng vừa đủ lớn để hoạt động tốt với JDK Hashtable, nhưng vẫn đủ nhỏ để giảm thiểu chi phí tính toán.
Thilo

2
Vâng, nó đánh tôi quá mà họ không thấy lớn. Nhưng bạn có tin rằng có một chi phí cao hơn với các số nguyên tố lớn hơn?
aioobe

3
@Thilo bạn sẽ cần bội số 1231 * 1237 = 1.522.747 xô trước khi chúng va chạm, điều đó đủ lớn
ratchet freak

2
Tôi muốn nói rằng dẫn đến va chạm với số lượng nhóm không thực sự là vấn đề với boolean, mà là cấu trúc phổ biến hơn về cách chúng ta lấy mã băm của một đối tượng tổng hợp, cụ thể là bằng cách nhân mã băm của các thành phần với một số hằng số và cộng chúng lại.
Drunix

2

Ngoài tất cả những gì đã nói ở trên, nó cũng có thể là một quả trứng Phục sinh nhỏ từ các nhà phát triển:

true: 1231 => 1 + 2 + 3 + 1 = 7

7 - là một con số may mắn trong truyền thống châu Âu;

sai: 1237 => 1 + 2 + 3 + 7 = 13

13 (hay còn gọi là Quỷ tá) ​​- con số không may mắn.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.