Nói một cách đơn giản hơn (tôi càng đơn giản càng tốt) + một số chi tiết khác.
Những thuộc tính này phụ thuộc vào rất nhiều thứ bên trong sẽ rất tuyệt để hiểu - trước khi chuyển trực tiếp đến chúng.
TREEIFY_THRESHOLD -> khi một nhóm duy nhất đạt đến con số này (và tổng số vượt quá MIN_TREEIFY_CAPACITY
), nó được chuyển thành một nút cây màu đỏ / đen cân bằng hoàn hảo . Tại sao? Vì tốc độ tìm kiếm. Hãy nghĩ về nó theo một cách khác:
sẽ mất nhiều nhất 32 bước để tìm kiếm Mục nhập trong một thùng / thùng có mục nhập Integer.MAX_VALUE .
Một số giới thiệu cho chủ đề tiếp theo. Tại sao số thùng / thùng luôn là lũy thừa của hai ? Ít nhất hai lý do: nhanh hơn hoạt động của modulo và modulo trên số âm sẽ là số âm. Và bạn không thể đặt Mục nhập vào nhóm "phủ định":
int arrayIndex = hashCode % buckets; // will be negative
buckets[arrayIndex] = Entry; // obviously will fail
Thay vào đó, có một thủ thuật hay được sử dụng thay vì modulo:
(n - 1) & hash // n is the number of bins, hash - is the hash function of the key
Điều đó về mặt ngữ nghĩa cũng giống như hoạt động modulo. Nó sẽ giữ các bit thấp hơn. Điều này có một hệ quả thú vị khi bạn làm:
Map<String, String> map = new HashMap<>();
Trong trường hợp trên, quyết định về vị trí của một mục nhập chỉ dựa trên 4 bit cuối cùng của mã băm của bạn.
Đây là lúc mà việc nhân lên các nhóm phát huy tác dụng. Trong những điều kiện nhất định (sẽ mất rất nhiều thời gian để giải thích chi tiết chính xác ), các thùng có kích thước gấp đôi. Tại sao? Khi các thùng được tăng kích thước lên gấp đôi, sẽ có một chút nữa phát huy tác dụng .
Vì vậy, bạn có 16 nhóm - 4 bit cuối cùng của mã băm quyết định vị trí của mục nhập. Bạn nhân đôi các nhóm: 32 nhóm - 5 bit cuối cùng quyết định mục nhập sẽ đi đến đâu.
Vì vậy, quá trình này được gọi là băm lại. Điều này có thể trở nên chậm chạp. Đó là (đối với những người quan tâm) như HashMap được "nói đùa" là: nhanh, nhanh, nhanh, slooow . Có các cách triển khai khác - bản đồ băm không tạm dừng tìm kiếm ...
Giờ đây, UNTREEIFY_THRESHOLD sẽ hoạt động sau khi băm lại. Tại thời điểm đó, một số mục nhập có thể di chuyển từ thùng này sang thùng khác (chúng thêm một bit nữa vào (n-1)&hash
tính toán - và như vậy có thể chuyển sang các thùng khác ) và nó có thể đạt được điều này UNTREEIFY_THRESHOLD
. Tại thời điểm này, việc giữ nguyên thùng rác không có lợi red-black tree node
, mà LinkedList
thay vào đó, như
entry.next.next....
MIN_TREEIFY_CAPACITY là số lượng nhóm tối thiểu trước khi một nhóm nhất định được chuyển đổi thành Cây.
String
, có không gian giá trị lớn hơn nhiều so với mãint
băm, do đó, xung đột là không thể tránh khỏi. Bây giờ nó phụ thuộc vào các giá trị thực tế, chẳng hạn như các giá trị thực tếString
, bạn đưa vào bản đồ, cho dù bạn có được phân phối đồng đều hay không. Một phân phối không tốt có thể là kết quả của vận rủi.