2014-11-08 19 views
5

Đoạn cuối cùng của Khoản 9 của Java hiệu quả, 2nd Edn, J. Bloch nói rằng, đối với các lớp học giá trị như Integer, String, Date vv, trở về một hàm của các giá trị chính xác về điều đó lớp học là hashCode không phải là ý tưởng hay.Tại sao giá trị của một lớp giá trị là hashCode của nó "không phải là một ý tưởng hay"?

Vì vậy, lớp Integer trả lại value của số nguyên nó đại diện như hashCode sơ thẩm của nó không phải là tất cả tốt như vậy.

Không phải là hashCode() của String trả lại giá trị số nguyên được ánh xạ trực tiếp từ nội dung tổng thể, tức là các ký tự mà phiên bản String có.

Những hashCode()-tuân thủ rõ ràng hợp đồng.

Với tôi, nó có vẻ là một ý tưởng hay thay vì xấu - hashCode -s thay đổi khi các giá trị khác nhau giữa các đối tượng và hashCodes được "chuẩn hóa" trước khi chúng được trải ra thành các thùng của HashMap/HashSet - để các hashCode -s của các mục không tạo thành một xu hướng mà bộ chứa các mục nhập sẽ đi vào

gì am i thiếu ở đây -. những gì làm cho việc lập bản đồ giá trị lớp trực tiếp đến hashCode một "xấu ý kiến"?

TIA

// ===========================

EDIT

pls cũng thấy bình luận dưới câu trả lời của Steve Siebert về vấn đề này.

Trả lời

4

gì nó nói là những đặc điểm kỹ thuật javadoc nói chính xác cách thức hashCode được tạo ra. Bằng cách đó, các ứng dụng bây giờ có thể phụ thuộc vào điều này luôn luôn đúng ... và bây giờ những triển khai đó không bao giờ có thể thay đổi cách hashCode được tạo ra.

Điều đó không có nghĩa là bạn không nên lấy băm từ giá trị của mình ...chỉ không nói với mọi người như thế nào bạn làm điều này trong đặc tả của bạn =)

+0

đồng ý với điều đó. nhưng giải pháp cho điều này nên bắt buộc một nguyên tắc là "không thể sử dụng hàm băm' hashCode' làm thay thế chỉ số/chức năng của 'giá trị'", thay vì hơn là nhận được mối quan hệ tốt đẹp giữa 'value' và' hashCode() 'và do đó giữa' equals() 'và' hashCode() '. – Roam

+0

Tôi hoàn toàn đồng ý với bạn, một hashCode có thể được coi là một hàm trả về biểu diễn "ít thông minh/mất dữ liệu" về giá trị thực của đối tượng - dễ bị nghịch lý sinh nhật. Nhưng, thực sự, một băm không cần thiết * cần * để có một relationhsip với giá trị ... hashCode cần phải luôn luôn trả về cùng một giá trị int cho cùng một đối tượng (tuy nhiên điều này được định nghĩa bởi bạn) để đối tượng có thể được tìm thấy trong xô dự kiến. Thông thường, điều này được thực hiện bằng cách băm một/nhiều giá trị của đối tượng ... có ý nghĩa. Nhưng, nếu nó có thể được thực hiện với, nói ... ma thuật ... vậy thì tôi là ai để phán xét? =) –

+0

bám 'hashCode' vào' value' có thể đảm bảo "nếu hai đối tượng không bằng nhau, không phải là hashCodes của chúng" và đó là điều tốt để có các mục phân phối đồng đều trên các nhóm băm-- mặc dù nó không một yêu cầu của hợp đồng. tôi không thấy và cũng không thể nghĩ ra cách tốt hơn để làm điều này. – Roam

-1

API Java thực hiện điều đó, nó trả về số nguyên.

Integer t = ...; 
t.intValue() == t.hashCode(); // true 

Tôi có cuốn sách tương tự tại nơi làm việc. Tôi sẽ xem nó vào thứ hai.

Nếu bạn thực sự lo lắng, thực hiện FNV-1a băm:

int hash = 0x4C1DF00D; 
    hash = (hash^value) * 0x01000193; 
+0

Tôi tự hỏi tại sao downvote? Tôi đã lên kế hoạch đến cùng một kết luận như @SotiriosDelimanolis, nhưng tôi có cuốn sách ở nơi khác và tôi không biết nó có sẵn cho trực tuyến miễn phí. –

3

Các full quote

Nhiều lớp trong thư viện nền tảng Java, chẳng hạn như String, Integer, và Date, bao gồm trong họ thông số kỹ thuật giá trị chính xác được trả về bởi phương thức hashCode của chúng như một hàm của giá trị mẫu. Điều này thường không phải là một ý tưởng hay vì nó giới hạn khả năng của bạn để cải thiện hàm băm trong các bản phát hành trong tương lai. Nếu bạn để lại các chi tiết của hàm băm không xác định và tìm thấy lỗi hoặc hàm băm tốt hơn, bạn có thể thay đổi hàm băm trong bản phát hành sau , tự tin rằng không có khách hàng nào phụ thuộc vào giá trị chính xác chức năng.

Mỏ nhấn mạnh. Cuốn sách chỉ nói rằng nó thường được coi là thực hành xấu để tiết lộ chi tiết thực hiện trong một đặc điểm kỹ thuật. Điều này làm cho nó có khả năng chống thay đổi.

Thực tế là nó đã được triển khai khi trả lại giá trị chính xác (cho Integer) hoặc một số giá trị được tính (cho DateString) không phải là xấu.

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