2010-09-26 3 views
31

यदि मैं किसी ऑब्जेक्ट पर Object.hashcode() विधि को कॉल करता हूं तो यह ऑब्जेक्ट का आंतरिक पता (डिफ़ॉल्ट कार्यान्वयन) देता है। क्या यह पता एक तार्किक या भौतिक पता है?विल .शैशकोड() कार्यकाल की गणना के कारण एक अलग int वापस कर देगा?

कचरा संग्रह में, मेमोरी कॉम्पैक्शन ऑब्जेक्ट्स स्थानांतरण के कारण मेमोरी में होता है। अगर मैं जीसी के पहले और बाद में हैशकोड को कॉल करता हूं, तो क्या यह उसी हैशकोड (यह लौटाता है) वापस करेगा और यदि हां तो क्यों (कॉम्पैक्शन पता बदलने के कारण)?

+0

यदि आप कुछ 'ऑब्जेक्ट.hashCode' के मान मुद्रित करते हैं, तो आप शायद देखेंगे कि वे पते होने की संभावना नहीं है। उदाहरण के लिए, किसी भी उचित कार्यान्वयन पर विषम संख्याएं। –

उत्तर

41

@erickson कम या ज्यादा सही है। java.lang.Object.hashCode() द्वारा लौटा गया हैशकोड ऑब्जेक्ट के जीवनकाल के लिए नहीं बदलता है।

जिस तरह से यह (आमतौर पर) लागू किया गया है वह चालाक है। जब किसी ऑब्जेक्ट को कचरा कलेक्टर द्वारा स्थानांतरित किया जाता है, तो इसके मूल हैशकोड को फिर से उपयोग किए जाने पर कहीं भी संग्रहीत किया जाना चाहिए। इसे लागू करने का स्पष्ट तरीका हैशकोड को पकड़ने के लिए ऑब्जेक्ट हेडर में 32 बिट फ़ील्ड जोड़ना होगा। लेकिन वह प्रत्येक ऑब्जेक्ट में 1 शब्द ओवरहेड जोड़ देगा, और सबसे सामान्य मामले में जगह बर्बाद कर देगा ... जहां ऑब्जेक्ट की hashCode विधि नहीं कहा जाता है।

समाधान ऑब्जेक्ट के ध्वज शब्द में दो ध्वज बिट्स जोड़ना है, और इन्हें निम्नानुसार (मोटे तौर पर) उपयोग करना है। पहला ध्वज सेट किया गया है जब hashCode विधि कहा जाता है। दूसरा फ्लैग hashCode विधि बताता है कि क्या ऑब्जेक्ट के वर्तमान पते को हैशकोड के रूप में उपयोग करना है, या संग्रहीत मूल्य का उपयोग करना है। जब जीसी किसी ऑब्जेक्ट को चलाता है और स्थानांतरित करता है, तो यह इन झंडे का परीक्षण करता है। यदि पहला ध्वज सेट किया गया है और दूसरा एक सेट नहीं है, तो जीसी ऑब्जेक्ट के अंत में एक अतिरिक्त शब्द आवंटित करता है और उस शब्द में मूल ऑब्जेक्ट स्थान संग्रहीत करता है। फिर यह दो झंडे सेट करता है। तब से, hashCode विधि ऑब्जेक्ट के अंत में शब्द से हैशकोड मान प्राप्त करती है।

"जब भी यह एक के दौरान एक बार से अधिक एक ही वस्तु पर शुरू हो जाती है:


वास्तव में, एक identityHashCode कार्यान्वयन इस तरह से व्यवहार करने के लिएgeneral hashCode contract के निम्न भाग को पूरा करने के है जावा एप्लिकेशन के निष्पादन, हैशकोड विधि को लगातार एक ही पूर्णांक वापस करना होगा, बशर्ते ऑब्जेक्ट पर तुलना के बराबर कोई भी जानकारी संशोधित न हो। यह पूर्णांक किसी अनुप्रयोग के निष्पादन से संगत नहीं रहना चाहिए एक ही आवेदन के दूसरे निष्पादन के लिए। "

identityHashCode() का एक काल्पनिक कार्यान्वयन कि बस एक वस्तु का वर्तमान मशीन पता लौटे हाइलाइट किए गए भाग का उल्लंघन करता है, तो/जब जीसी किसी दूसरे पते पर वस्तु ले जाया जाएगा। इसके आस-पास एकमात्र तरीका (hypothetical) JVM के लिए यह गारंटी देने के लिए होगा कि एक ऑब्जेक्ट कभी भी hashCode पर कॉल नहीं किया गया है। और इससे ढेर विखंडन के साथ गंभीर और अव्यवस्थित समस्याएं पैदा हो जाएंगी।

+1

ग्रेट स्पष्टीकरण स्टीफन! हैशकोड() के काम करने का आपका विवरण स्पष्ट करता है कि हैशकोड() प्रोग्राम चलाने के दौरान समान मूल्य को कैसे बनाए रखता है। इस बीच यदि कोई जीसी + मेमोरी कॉम्पैक्शन होता है, और एक नई ऑब्जेक्ट (जिसका हैशकोड() अभी तक नहीं लगाया गया है) पुराने स्थान के समान स्थान आवंटित किया गया है, तो हैशकोड() मान समान नहीं होगा सक्रिय ऑब्जेक्ट जिसने प्रारंभ में स्मृति स्थान पर कब्जा कर लिया था? यह ऑब्जेक्ट समानता और हैश आधारित संग्रह को कैसे प्रभावित करता है? –

+0

यह मेरे उत्तर के तीसरे अनुच्छेद द्वारा समझाया गया है। असल में, मूल पता/हैशकोड ऑब्जेक्ट के अंत में स्थानांतरित होने पर संग्रहीत किया जाता है। लेकिन केवल जब आवश्यक हो; यानी अगर केवल 'पहचान हैशकोड() '* को कॉल किया गया है। –

+0

मेरा मतलब था, ऑब्जेक्ट 1 में कोड 100 है और यह ऑब्जेक्ट 1 के अंत में अतिरिक्त शब्द में कॉपी किया गया है। इस बिंदु पर मान लीजिए कि एक जीसी कॉम्पैक्शन होता है और ऑब्जेक्ट 1 को कुछ और स्थानांतरित किया जाता है, जो नए आवंटन के लिए अपनी मूल मेमोरी लोकेशन को मुक्त करता है। मान लें कि कुछ संयोग के कारण ऑब्जेक्ट 1 के पुराने स्थान पर नया ऑब्जेक्ट 2 आवंटित किया गया है। ऑब्जेक्ट 2 का हैशकोड क्या होगा? क्या यह 100 नहीं होगा? TH \ उसका मतलब ऑब्जेक्ट 1 (अब कहीं और स्थानांतरित हो गया है, लेकिन पिछले शब्द में हैशकोड 100 सहेजा गया है) और ऑब्जेक्ट 2 (ऑब्जेक्ट 1 के पुराने स्थान पर आवंटित) एक ही हैशकोड साझा करेगा! –

0

इस link में यह कहता है कि वास्तव में डिफ़ॉल्ट हैश कोड ऑब्जेक्ट का JVM पता है, लेकिन यदि यह स्थानांतरित हो जाता है - पता लगातार रहता है। मुझे नहीं पता कि यह स्रोत कितना विश्वसनीय है, लेकिन मुझे यकीन है कि इस विधि के कार्यान्वयनकर्ताओं ने इस परिदृश्य (जो दुर्लभ या कोने का मामला नहीं है) के बारे में सोचा था, और इस विधि की सही कार्यक्षमता सुनिश्चित की।

4

नहीं, किसी ऑब्जेक्ट का डिफ़ॉल्ट हैश कोड नहीं बदलेगा।

प्रलेखन नहीं कहती कि हैश कोड है पता है, यह कहना है कि यह पर पते के आधार पर है। गौर करें कि हैश कोड 32 बिट हैं, लेकिन 64-बिट JVMs हैं। जाहिर है, सीधे पते का उपयोग करना हमेशा काम नहीं करेगा।

कार्यान्वयन JVM पर निर्भर करता है, लेकिन सूर्य (ओरेकल) जेवीएम में, मेरा मानना ​​है कि हैश कोड पहली बार कैश किया गया है।

+1

हैशकोड के जावा डॉक से: यह आमतौर पर ऑब्जेक्ट के आंतरिक पते को एक पूर्णांक – Ashish

+0

में परिवर्तित करके कार्यान्वित किया जाता है, जब जीसी किसी ऑब्जेक्ट को स्थानांतरित करता है तो हैशकोड कैश किया जाता है ... यदि 'हैशकोड()' पहले कहा गया है। –

+0

असल में आशीष, जावडोक यह कहता है: "यह आमतौर पर ऑब्जेक्ट के आंतरिक पते को एक पूर्णांक में परिवर्तित करके कार्यान्वित किया जाता है, ** लेकिन जावा प्रोग्रामिंग भाषा द्वारा इस कार्यान्वयन तकनीक की आवश्यकता नहीं है। **" दरअसल, हाल ही में जेवीएम के पास एक कमांड लाइन विकल्प जो आपको हैशकोड बनाने के लिए अन्य विधियों का चयन करने की अनुमति देता है। –

-1

यदि हैशकोड बदलता है, तो ऑब्जेक्ट एक हैश सेट में गायब हो जाएगा जिसमें इसे डाला गया था, और सूर्य शिकायतों के साथ बाढ़ आएगी।

0

हैशकोड के अनुबंध से यह इस कारण से नहीं बदला जा सकता है।

संबंधित मुद्दे