2009-09-04 16 views
9

क्या ऑब्जेक्ट के दो उदाहरणों के लिए एक ही हैशकोड संभव है?हैशकोड विशिष्टता

सिद्धांत रूप में एक वस्तु की hashCode अपनी स्मृति पते से ली गई है, इसलिए सभी hashcodes अद्वितीय होना चाहिए, लेकिन वस्तुओं जीसी दौरान चारों ओर ले जाया जाता है क्या है?

+0

यदि ऑब्जेक्ट्स चारों ओर स्थानांतरित हो जाते हैं, तो उनके पते भी बदल नहीं सकते हैं, और इसलिए उनके हैंशकोड? –

+0

@ विनीत: आप जावा में किसी वस्तु को "स्थानांतरित" कैसे करते हैं? – Brian

+0

@ ब्रायन, ओपी की चिंता कचरा संग्रह के संयोजन चरण के दौरान क्या होता है, इस बारे में प्रतीत होता है। Compaction के दौरान, वस्तुओं को पते पर ले जाया जा सकता है। –

उत्तर

11

वस्तुओं के उचित संग्रह को देखते हुए, एक ही हैश कोड के साथ दो होने की संभावना काफी है। सबसे अच्छे मामले में यह जन्मदिन की समस्या बन जाती है, जिसमें हजारों वस्तुओं के साथ संघर्ष होता है। प्रैक्टिस ऑब्जेक्ट्स में संभावित हैश कोड के अपेक्षाकृत छोटे पूल के साथ बनाया गया है, और केवल हजारों ऑब्जेक्ट्स के साथ संघर्ष आसानी से हो सकता है।

स्मृति पता का उपयोग करना थोड़ा यादृच्छिक संख्या प्राप्त करने का एक तरीका है। सूर्य जेडीके स्रोत में एक सुरक्षित रैंडम नंबर जेनरेटर या स्थिर के उपयोग को सक्षम करने के लिए एक स्विच है। मेरा मानना ​​है कि आईबीएम (इस्तेमाल किया जाता है?) एक तेज़ यादृच्छिक संख्या जनरेटर का उपयोग करता है, लेकिन यह बिल्कुल सुरक्षित नहीं था। स्मृति पते के दस्तावेज़ों में उल्लेख ऐतिहासिक प्रकृति का प्रतीत होता है (लगभग एक दशक पहले निश्चित स्थानों के साथ ऑब्जेक्ट हैंडल करना असामान्य नहीं था)। इस बात आती है, क्योंकि ऊपर जिस तरह से बहुत जल्दी-जल्दी,

class HashClash { 
    public static void main(String[] args) { 
     final Object obj = new Object(); 
     final int target = obj.hashCode(); 
     Object clash; 
     long ct = 0; 
     do { 
      clash = new Object(); 
      ++ct; 
     } while (clash.hashCode() != target && ct<10L*1000*1000*1000L); 
     if (clash.hashCode() == target) { 
      System.out.println(ct+": "+obj+" - "+clash); 
     } else { 
      System.out.println("No clashes found"); 
     } 
    } 
} 

RFE डॉक्स स्पष्ट करने के लिए:

यहाँ कुछ कोड मैं कुछ साल पहले लिखा था संघर्ष प्रदर्शित करने के लिए है CR 6321873

+0

तो क्या हम आसानी से कह सकते हैं कि डिफ़ॉल्ट हैशकोड जावा में विशिष्टता की गारंटी नहीं देगा? एक जेआरई के दिए गए कार्यान्वयन के लिए –

+0

। टक्कर खोजने के लिए एक छोटा कार्यक्रम लिखना आसान है। –

+0

मैंने जावा हॉटस्पॉट (टीएम) 64-बिट सर्वर वीएम (25.101-बी 13, मिश्रित मोड का निर्माण) पर कोड चलाया। इसे दो बार दौड़ें, यह हर 10 अरब बार केवल एक बार संघर्ष हुआ। और हमेशा एक ही हैशकोड के साथ! मुझे लगता है कि वे यादृच्छिक जेनरेटर बीज नहीं बदलते हैं (जो मुझे कंपकंपी बनाता है)। – sscarduzio

10

मुझे लगता है कि docs for object's hashCode method राज्य जवाब।

"जितना यथोचित व्यावहारिक है, hashCode विधि वर्ग वस्तु द्वारा परिभाषित अलग वस्तुओं के लिए अलग पूर्णांकों वापसी करता है। (यह आम तौर पर वस्तु की आंतरिक पता परिवर्तित एक में द्वारा कार्यान्वित है JavaTM भाषा प्रोग्रामिंग के लिए आवश्यक नहीं पूर्णांक है, लेकिन इस कार्यान्वयन तकनीक है।) "

+2

मैंने जावाडोक पढ़ा, लेकिन मुझे यह समझने की ज़रूरत नहीं है कि "उचित व्यावहारिक" का क्या अर्थ है। – Eleco

+3

कुछ आर्किटेक्चर पर शुरुआत के लिए पता स्थान एक int से बड़ा है, इसलिए दो अलग-अलग मान समान मूल्य उत्पन्न कर सकते हैं। – RichardOD

+0

@elec "उचित व्यावहारिक" का अर्थ है कि आप सभी (सीपीयू) लागतों पर बिल्कुल अद्वितीय बनाने के लिए 10k लाइन विधि नहीं लिखते हैं। – sal

4

क्या यह संभव है?

हां।

क्या यह किसी भी उचित आवृत्ति के साथ होता है?

सं।

+0

बिल्कुल यह। उन पर अनगिनत * गिनती न करें, लेकिन उनसे अपेक्षा न करें। –

+0

... जब तक आपके पास कई ऑब्जेक्ट्स न हों। आमतौर पर यह उचित आकार के हैश टेबल के लिए पर्याप्त हो सकता है। –

6

इसके बारे में सोचें। संभावित वस्तुओं की एक अनंत संख्या है, और केवल 4 अरब हैश कोड हैं। जाहिर है, संभावित वस्तुओं की अनंतता प्रत्येक हैश कोड साझा करती है।

सूर्य JVM या तो वस्तु के लिए एक स्थिर हैंडल पर ठिकानों Object हैश कोड या प्रारंभिक हैश कोड संचित करता है। जीसी के दौरान कॉम्पैक्शन hashCode() में बदलाव नहीं करेगा। अगर ऐसा होता तो सबकुछ टूट जाएगा।

+0

कुछ अच्छे अंक, लेकिन यह याद रखना महत्वपूर्ण है कि स्ट्रिंग के हैशकोड कार्यान्वयन (http://java.sun.com/j2se/1.4.2/docs/api/java/lang/String.html#hashCode()) नहीं है ऑब्जेक्ट के हैशकोड के समान कार्यान्वयन। – RichardOD

+0

धन्यवाद! मुझे बहुत देर हो गई कि सवाल ऑब्जेक्ट क्लास के कार्यान्वयन के लिए विशिष्ट था। मैंने स्ट्रिंग उदाहरण हटा दिए (हालांकि मुझे लगता है कि वे मजेदार हैं) और सूर्य जेवीएम के मूल कोड भाग को देखने से एकत्र की गई कुछ जानकारी जोड़ी गई। – erickson

+0

@erickson: मैं ऑब्जेक्ट कार्यान्वयन के मूल कोड को कहां देखना शुरू कर सकता हूं। Object.c खोलने के बाद खो गया प्रकार .... –

-2

अगर कोई स्मृति के रूप में थे के रूप में कई hashcodes पते, तो हैश को स्टोर करने के लिए संपूर्ण मेमोरी ले ली जाएगी। :-)

तो, हाँ, हैश कोड कभी-कभी मेल होना चाहिए।

+1

नहीं। ऐसे कंप्यूटर की कल्पना करें जिसमें 2^एन मेमोरी पते हों। एन बिट्स के साथ एक चर 2^एन विशिष्ट मानों को पकड़ने के लिए पर्याप्त रूप से बड़ा है। –

0

आप वास्तविक वर्ग Object या सामान्य रूप में वस्तुओं के बारे में बात कर रहे हैं? आप दोनों प्रश्नों का उपयोग करते हैं।(और असली दुनिया के ऐप्स आम तौर पर Object के बहुत से उदाहरण नहीं बनाते हैं)

सामान्य रूप से वस्तुओं के लिए, एक कक्षा लिखना आम है जिसके लिए आप equals() ओवरराइड करना चाहते हैं; और यदि आप ऐसा करते हैं, तो आपको hashCode() को ओवरराइड करना होगा ताकि "वर्ग" वाले उस वर्ग के दो अलग-अलग उदाहरणों में भी एक ही हैश कोड होना चाहिए। आपको उसी मामले के उदाहरणों के दौरान उस मामले में "डुप्लिकेट" हैश कोड प्राप्त होने की संभावना है।

साथ ही, विभिन्न कक्षाओं में hashCode() को लागू करते समय, वे अक्सर वस्तु में कुछ पर आधारित होते हैं, इसलिए आप कम "यादृच्छिक" मानों के साथ समाप्त होते हैं, जिसके परिणामस्वरूप विभिन्न वर्गों के उदाहरणों में "डुप्लिकेट" हैश कोड होते हैं (चाहे या नहीं वे वस्तुएं "बराबर" हैं)।

किसी वास्तविक दुनिया ऐप में, एक ही हैश कोड के साथ विभिन्न ऑब्जेक्ट्स को ढूंढना असामान्य नहीं है।

1

मुझे लगता है कि मूल प्रश्न डिफ़ॉल्ट Object कार्यान्वयन द्वारा उत्पन्न हैश कोड के बारे में है। तथ्य यह है कि हैश कोडों को समानता परीक्षण के लिए भरोसा नहीं किया जाना चाहिए और केवल कुछ विशिष्ट हैश मैपिंग परिचालनों में उपयोग किया जाता है (जैसे कि बहुत उपयोगी HashMap कार्यान्वयन द्वारा लागू)।

इस तरह उन्हें वास्तव में अद्वितीय होने की आवश्यकता नहीं है - उन्हें केवल बहुत सारे संघर्ष उत्पन्न करने के लिए पर्याप्त अद्वितीय होना चाहिए (जो HashMap कार्यान्वयन अक्षम कर देगा)।

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

समान हैश कोडों की आवश्यकता के समानता के बारे में केन के उत्तर को भी देखें।

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