2015-10-16 16 views
6

Theo this blog entry, HashMap reinvokes thực hiện riêng của mình hashCode() (được gọi là hash()) trên một hashcode nó đã được lấy ra.Tại sao và như thế nào HashMap có thực hiện nội bộ riêng của hashCode() gọi là hash()?

Nếu quan trọng là không null thì, nó sẽ gọi hashfunction trên đối tượng chủ chốt, xem dòng 4 trong phương pháp trên có nghĩa là key.hashCode(), vì vậy sau khi key.hashCode() trả về hashValue, dòng 4 trông giống như

int hash = hash (hashValue)

và bây giờ, nó áp dụng hàm băm hash trả về vào hàm băm riêng của nó.

Chúng tôi có thể tự hỏi tại sao chúng tôi lại tính toán hashvalue bằng hàm băm (hashValue). Trả lời là, Nó bảo vệ chống lại hàm băm chất lượng kém.

Có thể HashMap chính xác gán lại mã băm không? HashMap có thể lưu trữ các đối tượng, nhưng nó không có quyền truy cập vào logic gán một hashCode các đối tượng của nó. Ví dụ, hash() không thể nào tích hợp logic đằng sau hashCode() thực hiện như sau:

public class Employee { 
protected long employeeId; 
protected String firstName; 
protected String lastName; 

public int hashCode(){ 
    return (int) employeeId; 
} 

} 
+3

có thể trùng lặp của [Understanding lạ chức năng Java băm] (http://stackoverflow.com/questions/9335169/understanding-strange-java-hash-function) – Nayuki

+1

@NayukiMinase Đoán việc thực hiện của 'hash()' đã thay đổi theo thời gian, vì phiên bản 1.8.0_51 khác/đơn giản hơn (xem câu trả lời của tôi). – Andreas

Trả lời

13

Các hash() xuất phát là "cải thiện" mã băm từ mã băm thực tế, vì vậy thông bằng sẽ luôn luôn được đầu ra bằng nhau (từ jdk1 .8.0_51):

static final int hash(Object key) { 
    int h; 
    return (key == null) ? 0 : (h = key.hashCode())^(h >>> 16); 
} 

là tại sao mã băm cần cải tiến, đọc javadoc của phương pháp này:

tính key.hashCode() một d lây lan (XORs) bit cao hơn của băm xuống thấp hơn. Bởi vì bảng sử dụng mặt nạ power-of-two, các bộ băm chỉ thay đổi theo các bit trên mặt nạ hiện tại sẽ luôn luôn va chạm. (Trong số các ví dụ đã biết là tập hợp các phím Float giữ các số nguyên liên tiếp trong các bảng nhỏ.) Vì vậy, chúng tôi áp dụng một biến đổi làm tăng tác động của các bit cao hơn xuống. Có một sự cân bằng giữa tốc độ, tiện ích và chất lượng phân tán bit. Bởi vì nhiều bộ băm thông thường đã được phân phối hợp lý (vì vậy không được hưởng lợi từ việc lan truyền), và bởi vì chúng tôi sử dụng cây để xử lý các bộ va chạm lớn trong thùng, chúng tôi chỉ XOR một số bit được chuyển theo cách rẻ nhất có thể để giảm tổn thất hệ thống, cũng như kết hợp tác động của các bit cao nhất mà nếu không sẽ không bao giờ được sử dụng trong các phép tính chỉ mục vì các giới hạn bảng.

+2

Để nói theo cách khác, lớp 'HashMap' lấy các giá trị' hashCode() 'thô từ các đối tượng của nó và áp dụng phép biến đổi" làm trắng "một lần để cố gắng phân phối thậm chí nhiều hơn. – Nayuki

+0

@Andreas Tôi chấp nhận giải pháp! Cảm ơn. Bạn có thể liên kết tôi, hoặc có lẽ giải thích, những gì quyền lực của hai mặt nạ là? Tìm kiếm trên google cho thuật ngữ được tạo ra bằng không. – Muno

+1

@Muno Điện-of-hai mặt nạ đề cập đến thực tế là kích thước hashtable luôn luôn là một sức mạnh của hai (2,4,8,16,32, ...), do đó, để tính toán hashtable xô, một hoạt động bitmask đơn giản có thể được thực hiện (ví dụ 'h & 0x1F' cho kích thước Hashtable 32), nhanh hơn thao tác modulus ('% '). – Andreas

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